mainIndexSprite.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. "write": { x: 9, y: 4, w: 50, h: 48 },//商城分类设置icon
  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. * 计算图标显示宽高与缩放比(支持按宽度 size 或按高度 height 等比缩放)
  90. * @param {{ w: number, h: number }} icon 雪碧图坐标中的原始宽高
  91. * @param {{ size?: number|string, height?: number|string }} opts
  92. * @returns {{ displayW: number, displayH: number, scale: number }}
  93. */
  94. function resolveSpriteDisplaySize(icon, opts = {}) {
  95. const heightNum = Number(opts.height);
  96. const useHeight = opts.height !== "" && opts.height != null && !Number.isNaN(heightNum) && heightNum > 0;
  97. let scale;
  98. let displayW;
  99. let displayH;
  100. if (useHeight) {
  101. displayH = Math.round(heightNum);
  102. scale = displayH / icon.h;
  103. displayW = Math.round(icon.w * scale);
  104. } else {
  105. const sizeNum = Number(opts.size);
  106. displayW = !Number.isNaN(sizeNum) && sizeNum > 0 ? sizeNum : 48;
  107. scale = displayW / icon.w;
  108. displayH = Math.round(icon.h * scale);
  109. }
  110. return { displayW, displayH, scale };
  111. }
  112. /**
  113. * 解析图标所属雪碧图与坐标
  114. * @param {string} name 图标名
  115. * @param {string} sheetKey 可选,指定雪碧图 key;空则按索引或 main 查找
  116. * @returns {{ sheetKey: string, sheet: object, icon: object }|null}
  117. */
  118. export function resolveSprite(name, sheetKey = "") {
  119. if (!name) {
  120. return null;
  121. }
  122. let key = sheetKey;
  123. if (!key) {
  124. key = ICON_SHEET_INDEX[name] || DEFAULT_SHEET_KEY;
  125. }
  126. const sheet = SPRITE_SHEETS[key];
  127. if (!sheet) {
  128. return null;
  129. }
  130. const icon = (sheet.icons || {})[name];
  131. if (!icon) {
  132. return null;
  133. }
  134. return { sheetKey: key, sheet, icon };
  135. }
  136. /**
  137. * 获取指定雪碧图完整 URL
  138. * @param {string} sheetKey
  139. * @returns {string}
  140. */
  141. export function getSpriteSheetUrl(sheetKey = DEFAULT_SHEET_KEY) {
  142. const sheet = SPRITE_SHEETS[sheetKey];
  143. if (!sheet) {
  144. return "";
  145. }
  146. return `${getImgHostBase()}${sheet.path}`;
  147. }
  148. /**
  149. * 生成雪碧图 image 裁切样式(小程序 absolute 定位)
  150. * @param {string} name
  151. * @param {number|string} size 显示宽度 upx(未传 height 时生效)
  152. * @param {string} sheetKey 可选雪碧图 key
  153. * @param {number|string} height 显示高度 upx;传入后按高度等比缩放
  154. * @returns {{ wrap: string, inner: string, image: string }}
  155. */
  156. export function spriteImageStyle(name, size = 48, sheetKey = "", height = "") {
  157. const resolved = resolveSprite(name, sheetKey);
  158. if (!resolved) {
  159. if (process.env.NODE_ENV !== "production") {
  160. console.warn(`[sprite-icon] 未找到图标: name=${name}${sheetKey ? ` sheet=${sheetKey}` : ""}`);
  161. }
  162. return { wrap: "", inner: "", image: "" };
  163. }
  164. const { sheet, icon } = resolved;
  165. const { displayW, displayH, scale } = resolveSpriteDisplaySize(icon, { size, height });
  166. const sheetW = sheet.width * scale;
  167. const sheetH = sheet.height * scale;
  168. const left = -rpx2px(icon.x * scale);
  169. const top = -rpx2px(icon.y * scale);
  170. const sheetWPx = rpx2px(sheetW);
  171. const sheetHPx = rpx2px(sheetH);
  172. return {
  173. wrap: `position:relative;width:${displayW}rpx;height:${displayH}rpx;overflow:hidden;line-height:0;`,
  174. inner: `position:absolute;left:${left}px;top:${top}px;width:${sheetWPx}px;height:${sheetHPx}px;`,
  175. image: "width:100%;height:100%;display:block;"
  176. };
  177. }
  178. /**
  179. * 生成雪碧图行内样式(view + background)
  180. * @param {string} name
  181. * @param {number|string} size
  182. * @param {string} sheetKey
  183. * @param {number|string} height
  184. * @returns {string}
  185. */
  186. export function spriteStyle(name, size = 48, sheetKey = "", height = "") {
  187. const resolved = resolveSprite(name, sheetKey);
  188. if (!resolved) {
  189. return "";
  190. }
  191. const { sheetKey: key, sheet, icon } = resolved;
  192. const { displayW, displayH, scale } = resolveSpriteDisplaySize(icon, { size, height });
  193. const sheetW = sheet.width * scale;
  194. const sheetH = sheet.height * scale;
  195. const posX = rpx2px(icon.x * scale);
  196. const posY = rpx2px(icon.y * scale);
  197. const sheetWPx = rpx2px(sheetW);
  198. const sheetHPx = rpx2px(sheetH);
  199. const url = getSpriteSheetUrl(key);
  200. return [
  201. `width:${displayW}rpx`,
  202. `height:${displayH}rpx`,
  203. `background-image:url(${url})`,
  204. `background-size:${sheetWPx}px ${sheetHPx}px`,
  205. `background-position:-${posX}px -${posY}px`,
  206. "background-repeat:no-repeat",
  207. "display:inline-block",
  208. "flex-shrink:0",
  209. "vertical-align:middle"
  210. ].join(";");
  211. }
  212. /** @deprecated 兼容旧 API */
  213. export function getMainIndexSpriteUrl() {
  214. return getSpriteSheetUrl(DEFAULT_SHEET_KEY);
  215. }
  216. /** @deprecated 兼容旧 API */
  217. export function mainIndexSpriteImageStyle(name, size = 48, height = "") {
  218. return spriteImageStyle(name, size, DEFAULT_SHEET_KEY, height);
  219. }
  220. /** @deprecated 兼容旧 API */
  221. export function mainIndexSpriteStyle(name, size = 48, height = "") {
  222. return spriteStyle(name, size, DEFAULT_SHEET_KEY, height);
  223. }