mainIndexSprite.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /**
  2. * 雪碧图注册表
  3. * 用途:sprite-icon 按 sheet + name 从多张 CDN 雪碧图裁切显示图标
  4. * 图片地址随 ext.json / 环境 imgHost 变化,必须用函数运行时读取
  5. */
  6. import constant from "@/constant/index";
  7. /** 默认图床(ext 未配置 imgHost 时的兜底) */
  8. const DEFAULT_IMG_HOST = "https://img.huaml.com";
  9. /** 未传 sheet 时默认使用的雪碧图 key */
  10. const DEFAULT_SHEET_KEY = "main";
  11. /**
  12. * 雪碧图注册表:每张图含 path、原图尺寸、icons 坐标
  13. * icons 的 x/y 为左上角,w/h 为截取区域(基于原图测量)
  14. */
  15. export const SPRITE_SHEETS = {
  16. main: {
  17. path: "/hzg/sprite_icon/main_index.webp",
  18. width: 500,
  19. height: 500,
  20. icons: {
  21. "dengji-biandong": { x: 14, y: 17, w: 32, h: 28 },
  22. }
  23. },
  24. /** 进货/供货商专用雪碧图,坐标待设计稿测量后补全 */
  25. /* stock: {
  26. path: "/hzg/sprite_icon/main_index.webp?time=2607101747",
  27. width: 500,
  28. height: 500,
  29. icons: {
  30. "yue-biandong": { x: 60, y: 17, w: 28, h: 28 }
  31. }
  32. } */
  33. };
  34. /** tabBar 未选中 / 选中 图标名映射(main 雪碧图) */
  35. export const TAB_SPRITE_MAP = {
  36. home: { normal: "dianpu-line", active: "dianpu-fill" },
  37. order: { normal: "huoche-lv", active: "huoche-da" },
  38. mine: { normal: "gou-quan", active: "qianbao" }
  39. };
  40. /** @deprecated 兼容旧引用,等同 SPRITE_SHEETS.main 尺寸 */
  41. export const MAIN_INDEX_SPRITE = {
  42. width: SPRITE_SHEETS.main.width,
  43. height: SPRITE_SHEETS.main.height
  44. };
  45. /** @deprecated 兼容旧引用,等同 SPRITE_SHEETS.main.icons */
  46. export const MAIN_INDEX_ICONS = SPRITE_SHEETS.main.icons;
  47. /**
  48. * 构建全局唯一图标名 -> sheetKey 索引
  49. * @param {object} sheets
  50. * @returns {object}
  51. */
  52. function buildIconSheetIndex(sheets) {
  53. const index = {};
  54. Object.keys(sheets).forEach((sheetKey) => {
  55. const icons = sheets[sheetKey].icons || {};
  56. Object.keys(icons).forEach((name) => {
  57. if (index[name] && index[name] !== sheetKey && process.env.NODE_ENV !== "production") {
  58. console.warn(`[sprite] 图标名 "${name}" 在 ${index[name]} 与 ${sheetKey} 中重复,以 ${sheetKey} 为准`);
  59. }
  60. index[name] = sheetKey;
  61. });
  62. });
  63. return index;
  64. }
  65. const ICON_SHEET_INDEX = buildIconSheetIndex(SPRITE_SHEETS);
  66. /**
  67. * 获取图床根地址(HTTPS)
  68. * @returns {string}
  69. */
  70. function getImgHostBase() {
  71. let base = (constant.imgUrl || DEFAULT_IMG_HOST).replace(/\/$/, "");
  72. if (base.indexOf("http://") === 0) {
  73. base = `https://${base.slice(7)}`;
  74. }
  75. return base;
  76. }
  77. /**
  78. * rpx 转 px;小程序 absolute 位移必须用 px
  79. * @param {number} rpx
  80. * @returns {number}
  81. */
  82. function rpx2px(rpx) {
  83. if (typeof uni !== "undefined" && typeof uni.upx2px === "function") {
  84. return uni.upx2px(rpx);
  85. }
  86. return rpx;
  87. }
  88. /**
  89. * 解析图标所属雪碧图与坐标
  90. * @param {string} name 图标名
  91. * @param {string} sheetKey 可选,指定雪碧图 key;空则按索引或 main 查找
  92. * @returns {{ sheetKey: string, sheet: object, icon: object }|null}
  93. */
  94. export function resolveSprite(name, sheetKey = "") {
  95. if (!name) {
  96. return null;
  97. }
  98. let key = sheetKey;
  99. if (!key) {
  100. key = ICON_SHEET_INDEX[name] || DEFAULT_SHEET_KEY;
  101. }
  102. const sheet = SPRITE_SHEETS[key];
  103. if (!sheet) {
  104. return null;
  105. }
  106. const icon = (sheet.icons || {})[name];
  107. if (!icon) {
  108. return null;
  109. }
  110. return { sheetKey: key, sheet, icon };
  111. }
  112. /**
  113. * 获取指定雪碧图完整 URL
  114. * @param {string} sheetKey
  115. * @returns {string}
  116. */
  117. export function getSpriteSheetUrl(sheetKey = DEFAULT_SHEET_KEY) {
  118. const sheet = SPRITE_SHEETS[sheetKey];
  119. if (!sheet) {
  120. return "";
  121. }
  122. return `${getImgHostBase()}${sheet.path}`;
  123. }
  124. /**
  125. * 生成雪碧图 image 裁切样式(小程序 absolute 定位)
  126. * @param {string} name
  127. * @param {number|string} size 显示宽度 rpx
  128. * @param {string} sheetKey 可选雪碧图 key
  129. * @returns {{ wrap: string, inner: string, image: string }}
  130. */
  131. export function spriteImageStyle(name, size = 48, sheetKey = "") {
  132. const resolved = resolveSprite(name, sheetKey);
  133. if (!resolved) {
  134. if (process.env.NODE_ENV !== "production") {
  135. console.warn(`[sprite-icon] 未找到图标: name=${name}${sheetKey ? ` sheet=${sheetKey}` : ""}`);
  136. }
  137. return { wrap: "", inner: "", image: "" };
  138. }
  139. const { sheet, icon } = resolved;
  140. const displayW = Number(size) || 48;
  141. const scale = displayW / icon.w;
  142. const displayH = Math.round(icon.h * scale);
  143. const sheetW = sheet.width * scale;
  144. const sheetH = sheet.height * scale;
  145. const left = -rpx2px(icon.x * scale);
  146. const top = -rpx2px(icon.y * scale);
  147. const sheetWPx = rpx2px(sheetW);
  148. const sheetHPx = rpx2px(sheetH);
  149. return {
  150. wrap: `position:relative;width:${displayW}rpx;height:${displayH}rpx;overflow:hidden;line-height:0;`,
  151. inner: `position:absolute;left:${left}px;top:${top}px;width:${sheetWPx}px;height:${sheetHPx}px;`,
  152. image: "width:100%;height:100%;display:block;"
  153. };
  154. }
  155. /**
  156. * 生成雪碧图行内样式(view + background)
  157. * @param {string} name
  158. * @param {number|string} size
  159. * @param {string} sheetKey
  160. * @returns {string}
  161. */
  162. export function spriteStyle(name, size = 48, sheetKey = "") {
  163. const resolved = resolveSprite(name, sheetKey);
  164. if (!resolved) {
  165. return "";
  166. }
  167. const { sheetKey: key, sheet, icon } = resolved;
  168. const displayW = Number(size) || 48;
  169. const scale = displayW / icon.w;
  170. const displayH = Math.round(icon.h * scale);
  171. const sheetW = sheet.width * scale;
  172. const sheetH = sheet.height * scale;
  173. const posX = rpx2px(icon.x * scale);
  174. const posY = rpx2px(icon.y * scale);
  175. const sheetWPx = rpx2px(sheetW);
  176. const sheetHPx = rpx2px(sheetH);
  177. const url = getSpriteSheetUrl(key);
  178. return [
  179. `width:${displayW}rpx`,
  180. `height:${displayH}rpx`,
  181. `background-image:url(${url})`,
  182. `background-size:${sheetWPx}px ${sheetHPx}px`,
  183. `background-position:-${posX}px -${posY}px`,
  184. "background-repeat:no-repeat",
  185. "display:inline-block",
  186. "flex-shrink:0",
  187. "vertical-align:middle"
  188. ].join(";");
  189. }
  190. /** @deprecated 兼容旧 API */
  191. export function getMainIndexSpriteUrl() {
  192. return getSpriteSheetUrl(DEFAULT_SHEET_KEY);
  193. }
  194. /** @deprecated 兼容旧 API */
  195. export function mainIndexSpriteImageStyle(name, size = 48) {
  196. return spriteImageStyle(name, size, DEFAULT_SHEET_KEY);
  197. }
  198. /** @deprecated 兼容旧 API */
  199. export function mainIndexSpriteStyle(name, size = 48) {
  200. return spriteStyle(name, size, DEFAULT_SHEET_KEY);
  201. }