UNPKG

@kangwuyi/vue3-sketch-ruler

Version:
480 lines (479 loc) 16.2 kB
import { h as Y, defineComponent as q, inject as R, ref as C, computed as M, createElementBlock as T, openBlock as p, withModifiers as j, normalizeStyle as A, normalizeClass as z, createElementVNode as O, toDisplayString as _, watch as F, onMounted as ce, createVNode as H, createCommentVNode as G, withDirectives as ue, unref as K, Fragment as ee, renderList as de, createBlock as Z, vShow as he, mergeDefaults as ve, provide as $ } from "vue"; import fe from "lodash"; /** * @license @tabler/icons-vue v3.31.0 - MIT * * This source code is licensed under the MIT license. * See the LICENSE file in the root directory of this source tree. */ var W = { outline: { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": 2, "stroke-linecap": "round", "stroke-linejoin": "round" }, filled: { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "currentColor", stroke: "none" } }; /** * @license @tabler/icons-vue v3.31.0 - MIT * * This source code is licensed under the MIT license. * See the LICENSE file in the root directory of this source tree. */ const te = (e, t, u, s) => ({ color: d = "currentColor", size: i = 24, stroke: v = 2, title: r, class: h, ...L }, { attrs: n, slots: g }) => { let o = [...s.map((a) => Y(...a)), ...g.default ? [g.default()] : []]; return r && (o = [Y("title", r), ...o]), Y( "svg", { ...W[e], width: i, height: i, ...n, class: ["tabler-icon", `tabler-icon-${t}`], ...e === "filled" ? { fill: d } : { "stroke-width": v ?? W[e]["stroke-width"], stroke: d }, ...L }, o ); }; /** * @license @tabler/icons-vue v3.31.0 - MIT * * This source code is licensed under the MIT license. * See the LICENSE file in the root directory of this source tree. */ var me = te("outline", "eye-x", "IconEyeX", [["path", { d: "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0", key: "svg-0" }], ["path", { d: "M13.048 17.942a9.298 9.298 0 0 1 -1.048 .058c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6a17.986 17.986 0 0 1 -1.362 1.975", key: "svg-1" }], ["path", { d: "M22 22l-5 -5", key: "svg-2" }], ["path", { d: "M17 22l5 -5", key: "svg-3" }]]); /** * @license @tabler/icons-vue v3.31.0 - MIT * * This source code is licensed under the MIT license. * See the LICENSE file in the root directory of this source tree. */ var ge = te("outline", "eye", "IconEye", [["path", { d: "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0", key: "svg-0" }], ["path", { d: "M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6", key: "svg-1" }]]); const I = { bgColor: "#171a24", // ruler bg color // 刻度尺 longfgColor: "#3B3B3B", // ruler longer mark color shortfgColor: "#3B3B3B", // ruler shorter mark color fontColor: "#f3f3f3", // ruler font color shadowColor: "#3275ff1a", // ruler shadow color lineColor: "#E02020", borderColor: "#3B3B3B", cornerActiveColor: "rgb(235, 86, 72, 0.6)" }; var B = /* @__PURE__ */ ((e) => (e.DEL = "del", e.ADD = "add", e.UPDATE = "update", e))(B || {}), D = /* @__PURE__ */ ((e) => (e.HORIZONTAL = "horizontal", e.VERTICAL = "vertical", e))(D || {}); const P = Symbol("lineListCb"), Ne = { lineList: { horizontal: [], vertical: [] }, updateLineList: () => { } }, ie = { x: 0, y: 0, width: 0, height: 0 }, ne = Symbol("rect"), le = window.devicePixelRatio || 1, oe = Symbol("wdpRatio"), U = 1, X = Symbol("scaleFigure"), be = ["tabindex"], Le = { class: "value" }, ke = /* @__PURE__ */ q({ __name: "line", props: { start: { type: Number, required: !0 }, isVertical: { type: Boolean, required: !0 }, rollback: { type: Number, required: !0 }, value: { type: Number, required: !0 }, thick: { type: Number, required: !0 } }, emits: ["onIsMovingStart", "onIsMovingEnd", "onUpdateLine"], setup(e, { emit: t }) { const u = R(X, C(U)), s = R(P, () => { }), d = t, i = C(e.value), v = M(() => ({ [e.isVertical ? "top" : "left"]: `${(i.value - e.start) * u.value}px`, [e.isVertical ? "borderTop" : "borderLeft"]: `1px solid ${I.lineColor}`, // ns↕️ ew↔️ cursor: e.isVertical ? "ns-resize" : "ew-resize", [e.isVertical ? "width" : "height"]: `${e.rollback + e.thick}px` })), r = M(() => ({ [e.isVertical ? "left" : "top"]: `${e.thick - (e.isVertical, 22)}px` })), h = (n) => { d("onIsMovingStart"); const g = e.isVertical ? n.clientY : n.clientX, o = i.value, a = (y) => { const k = e.isVertical ? y.clientY : y.clientX, l = Math.round(o + (k - g) / u.value); i.value = l; }, c = () => { d("onIsMovingEnd"), d("onUpdateLine", i.value), document.removeEventListener("mousemove", a), document.removeEventListener("mouseup", c); }; document.addEventListener("mousemove", a), document.addEventListener("mouseup", c); }, L = () => s( e.isVertical ? D.VERTICAL : D.HORIZONTAL, B.DEL, e.value ); return (n, g) => (p(), T("div", { class: z({ "ruler-_-line": !0, "ruler-_-line-v": e.isVertical, "ruler-_-line-h": !e.isVertical }), style: A(v.value), onDblclick: j(L, ["stop", "prevent"]), onMousedown: j(h, ["stop", "prevent"]), tabindex: e.value }, [ O("div", { class: "action", style: A(r.value) }, [ O("span", Le, _(i.value), 1) ], 4) ], 46, be)); } }), Ve = (e) => e <= 0.25 ? 40 : e <= 0.5 ? 20 : e <= 1 ? 10 : e <= 2 ? 5 : e <= 4 ? 2 : 1, J = 0.83, we = (e, t, u, s, d) => { const { scale: i, width: v, height: r, ratio: h } = d, { bgColor: L, fontColor: n, shadowColor: g, longfgColor: o, shortfgColor: a } = I; if (t.scale(h, h), t.clearRect(0, 0, v, r), t.fillStyle = L, t.fillRect(0, 0, v, r), s) { const m = ((e ? s.y : s.x) - u) * i, E = (e ? s.height : s.width) * i; t.fillStyle = g; const V = e ? 0 : m, re = e ? m : 0, ae = e ? v : E, se = e ? E : r; t.fillRect(V, re, ae, se); } const c = Ve(i), y = c * i, k = c * 10, l = k * i, b = Math.floor(u / c) * c, w = Math.floor(u / k) * k, f = (b - u) / c * y, S = (w - u) / k * l, N = u + Math.ceil((e ? r : v) / i); t.beginPath(), t.fillStyle = n, t.strokeStyle = o, t.font = '"PingFang SC","Microsoft YaHei"'; for (let m = w, E = 0; m < N; m += k, E += 1) { const V = S + E * l + 0.5; e ? t.moveTo(0, V) : t.moveTo(V, 0), t.save(), e ? t.translate(v * 0.4, V) : t.translate(V, r * 0.4), e && t.rotate(-Math.PI / 2), t.scale(J / h, J / h), t.fillText(String(m), 4 * h, 9 * h), t.restore(), e ? t.lineTo(v * 15 / 16, V) : t.lineTo(V, r * 15 / 16); } t.stroke(), t.closePath(), t.beginPath(), t.strokeStyle = a; for (let m = b, E = 0; m < N; m += c, E += 1) { const V = f + E * y + 0.5; e ? t.moveTo(0, V) : t.moveTo(V, 0), m % k !== 0 && (e ? t.lineTo(v * 1 / 4, V) : t.lineTo(V, r * 1 / 4)); } t.stroke(), t.closePath(), t.setTransform(1, 0, 0, 1, 0, 0); }, ye = /* @__PURE__ */ q({ __name: "canvas", props: { isVertical: { type: Boolean, required: !0 }, lineVisible: { type: Boolean, required: !0 }, start: { type: Number, required: !0 }, width: { type: Number, required: !0 }, height: { type: Number, required: !0 } }, emits: ["onLineVisible", "onLineMove", "onLineDisable", "onLineMoveEnd"], setup(e, { emit: t }) { const u = t, s = R(oe, C(le)); F(s, (l) => { }, { deep: !0 }); const d = R(X, C(U)), i = R( ne, M(() => ie) ); F( [i, d], ([l, b]) => { o(); }, { deep: !0 } ); const v = R(P, () => { }), r = (l, b, w) => Math.round(b + l / w), h = C(null), L = C(null), n = e; F( () => [n.start], () => { o(); } ), F( () => [n.width, n.height], () => { g(), o(); } ), ce(() => { g(), o(); }); const g = () => { if (!h.value) return; h.value.width = n.width * s.value, h.value.height = n.height * s.value; const l = h.value.getContext("2d"); l.font = `normal ${12 * s.value}px 'PingFang SC', 'Microsoft YaHei', monospace, sans-serif`, l.lineWidth = 1, l.textBaseline = "middle", L.value = l; }, o = () => { if (!L.value) return; const l = { scale: d.value, ratio: s.value, width: n.width, height: n.height }; we( n.isVertical, L.value, n.start, { x: n.isVertical ? 0 : i.value.x, width: n.isVertical ? 0 : i.value.width, y: n.isVertical ? i.value.y : 0, height: n.isVertical ? i.value.height : 0 }, l ); }, a = (l) => { const b = n.isVertical ? l.offsetY : l.offsetX, w = r(b, n.start, d.value); v( n.isVertical ? D.VERTICAL : D.HORIZONTAL, B.ADD, w ); }, c = (l) => { const b = n.isVertical ? l.offsetY : l.offsetX, w = r(b, n.start, d.value); u("onLineVisible", w); }, y = (l) => { const b = n.isVertical ? l.offsetY : l.offsetX, w = r(b, n.start, d.value); u("onLineMove", w); }, k = () => u("onLineMoveEnd", !1); return (l, b) => (p(), T("canvas", { class: z({ "ruler-_-canvas": !0, "ruler-_-canvas-noevent": !e.lineVisible }), ref_key: "canvasRef", ref: h, onClick: a, onMouseenter: c, onMousemove: y, onMouseleave: k }, null, 34)); } }), Ce = { key: 0, class: "ruler-_-line-box" }, Me = { class: "value" }, Q = /* @__PURE__ */ q({ __name: "wrapper", props: { isVertical: { type: Boolean, required: !0 }, width: { type: Number, required: !0 }, height: { type: Number, required: !0 }, thick: { type: Number, required: !0 }, // 缓存被 thick 替换的宽高 rollback: { type: Number, required: !0, defalut: 0 }, start: { type: Number, required: !0 }, lineVisible: { type: Boolean, required: !0 }, markLineList: Array }, emits: ["update:lineVisible"], setup(e, { emit: t }) { const u = R(P, () => { }), s = R(X, C(U)), d = t, i = e, v = M(() => { const f = { width: `calc(100% - ${i.thick}px)`, height: `${i.thick}px`, left: `${i.thick}px` }, S = { width: `${i.thick}px`, height: `calc(100% - ${i.thick}px)`, top: `${i.thick}px` }; return i.isVertical ? S : f; }), r = C(0), h = M(() => ({ [i.isVertical ? "top" : "left"]: `${(r.value - i.start) * s.value}px`, [i.isVertical ? "borderTop" : "borderLeft"]: `1px dashed ${I.cornerActiveColor}`, [i.isVertical ? "width" : "height"]: `${i.rollback + i.thick}px` })), L = (f) => { k.value || (r.value = f), y(!0); }, n = fe.debounce((f) => { r.value = f; }, 1), g = () => y(!1), o = () => d("update:lineVisible", !1), a = (f) => { const S = f - i.start, N = (i.isVertical ? i.height : i.width) / s.value, m = i.isVertical ? D.VERTICAL : D.HORIZONTAL; S < 0 || S > N ? u(m, B.DEL, f) : u(m, B.UPDATE, f); }, c = C(!1), y = (f) => c.value = f, k = C(!1), l = (f) => k.value = f, b = () => { l(!0), y(!1); }, w = () => { l(!1); }; return (f, S) => (p(), T("div", { class: z({ "ruler-_-wrapper": !0, "ruler-_-wrapper-v": e.isVertical, "ruler-_-wrapper-h": !e.isVertical }), style: A(v.value) }, [ H(ye, { lineVisible: e.lineVisible, isVertical: e.isVertical, width: e.width, height: e.height, start: e.start, onOnLineMove: K(n), onOnLineMoveEnd: g, onOnLineVisible: L, onOnLineDisable: o }, null, 8, ["lineVisible", "isVertical", "width", "height", "start", "onOnLineMove"]), e.lineVisible ? (p(), T("div", Ce, [ (p(!0), T(ee, null, de(e.markLineList, (N, m) => (p(), Z(ke, { key: "line" + N, index: m, start: e.start, isVertical: e.isVertical, rollback: e.rollback, thick: e.thick, value: N >> 0, onOnIsMovingEnd: w, onOnIsMovingStart: b, onOnUpdateLine: a }, null, 8, ["index", "start", "isVertical", "rollback", "thick", "value"]))), 128)) ])) : G("", !0), c.value ? ue((p(), T("div", { key: 1, class: "indicator", style: A(h.value) }, [ O("div", Me, _(r.value), 1) ], 4)), [ [he, e.lineVisible] ]) : G("", !0) ], 6)); } }), x = /* @__PURE__ */ q({ __name: "ruler", props: /* @__PURE__ */ ve({ // 变量 // Window.devicePixelRatio = {物理像素分辨率/CSS 像素分辨率} wdpRatio: Number, // ------------------ scaleFigure: Number, // 传入阴影部分,选中画布组件,在标尺中标注组件位置 rect: Object, // 常量 thick: Number, width: Number, height: Number, startX: Number, startY: Number, markLineList: Array }, { wdpRatio: le, __skip_wdpRatio: !0, scaleFigure: U, __skip_scaleFigure: !0, rect: ie, __skip_rect: !0, thick: 24, width: 0, height: 0, startX: 0, startY: 0, markLineList: () => [] }), emits: [ // 选中组件的坐标值发生改变, rect.rect|rect.y // 可能的情况,选中组件移动过程中发生吸附其他组件或中轴线或边界线 // 标注线 "onMarkLineList" ], setup(e, { emit: t }) { const u = t, s = M(() => e.wdpRatio); $(oe, s); const d = M(() => e.scaleFigure); $(X, d), $("updateRect", () => { }); const v = M(() => e.rect); $(ne, v); const r = M( () => e.markLineList.reduce((o, a) => (o.horizontal || (o.horizontal = []), o.vertical || (o.vertical = []), a.type === "horizontal" ? o.horizontal.push(a.value) : a.type === "vertical" && o.vertical.push(a.value), o), {}) ); $(P, (o, a, c) => { u("onMarkLineList", o, a, c); }); const L = M(() => ({ backgroundColor: I.bgColor, width: `${e.thick}px`, height: `${e.thick}px`, borderRight: `1px solid ${I.borderColor}`, borderBottom: `1px solid ${I.borderColor}` })), n = C(!1), g = () => n.value = !n.value; return (o, a) => (p(), T(ee, null, [ H(Q, { isVertical: !1, markLineList: r.value.horizontal, width: e.width, height: e.thick, thick: e.thick, rollback: e.height, start: e.startX, lineVisible: n.value, "onUpdate:lineVisible": a[0] || (a[0] = (c) => n.value = c) }, null, 8, ["markLineList", "width", "height", "thick", "rollback", "start", "lineVisible"]), H(Q, { isVertical: !0, markLineList: r.value.vertical, width: e.thick, height: e.height, thick: e.thick, rollback: e.width, start: e.startY, lineVisible: n.value, "onUpdate:lineVisible": a[1] || (a[1] = (c) => n.value = c) }, null, 8, ["markLineList", "width", "height", "thick", "rollback", "start", "lineVisible"]), O("span", { class: z(["", { "ruler-_-corner": !0 }]), style: A(L.value), onClick: g }, [ n.value ? (p(), Z(K(ge), { key: 0, class: "ruler-_-corner-icon" })) : (p(), Z(K(me), { key: 1, class: "ruler-_-corner-icon" })) ], 4) ], 64)); } }); x.install = function(e) { e.component("imp-sketch-ruler", x); }; const pe = [x], Ee = function(e) { pe.forEach((t) => { e.component("imp-sketch-ruler", t); }); }, Te = { // 导出的对象必须具有 install,才能被 app.use() 方法安装 install: Ee, SketchRuler: x }; export { Ne as DEFAULT_LINELIST, ie as DEFAULT_RECT, U as DEFAULT_SCALE_FIGURE, I as DEFAULT_THEME, le as DEFAULT_WDP_RATIO, B as ELineActionType, D as ELineDirectionType, Te as default, P as lineListCbKey, ne as rectKey, X as scaleFigureKey, oe as wdpRatioKey };