151 lines
3.9 KiB
JavaScript
151 lines
3.9 KiB
JavaScript
"use strict";
|
|
const common_vendor = require("../../common/vendor.js");
|
|
const _sfc_main = {
|
|
props: {
|
|
width: Number,
|
|
// 画布实际宽度(像素)
|
|
height: Number,
|
|
// 画布实际高度(像素)
|
|
imgUrl: String,
|
|
// 图片URL
|
|
matrix: {
|
|
// 变换矩阵
|
|
type: Object,
|
|
default: () => ({
|
|
a: 1,
|
|
b: 0,
|
|
c: 0,
|
|
d: 1,
|
|
tx: 0,
|
|
ty: 0
|
|
})
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
canvasContext: null,
|
|
image: null,
|
|
dpr: 1,
|
|
canvasDisplayWidth: 300,
|
|
// 默认显示尺寸
|
|
canvasDisplayHeight: 300,
|
|
canvasActualWidth: 300,
|
|
// 实际像素尺寸
|
|
canvasActualHeight: 300
|
|
};
|
|
},
|
|
watch: {
|
|
imgUrl: {
|
|
handler(newUrl) {
|
|
if (newUrl)
|
|
this.loadImage(newUrl);
|
|
},
|
|
immediate: true
|
|
},
|
|
width: {
|
|
handler() {
|
|
this.updateCanvasSize();
|
|
},
|
|
immediate: true
|
|
},
|
|
height: {
|
|
handler() {
|
|
this.updateCanvasSize();
|
|
},
|
|
immediate: true
|
|
},
|
|
matrix: {
|
|
deep: true,
|
|
handler() {
|
|
this.$nextTick(() => {
|
|
if (this.canvasContext) {
|
|
this.redraw();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.initCanvas();
|
|
},
|
|
methods: {
|
|
initCanvas() {
|
|
const query = common_vendor.index.createSelectorQuery().in(this);
|
|
query.select("#myCanvas").fields({ node: true, size: true }).exec(async (res) => {
|
|
if (!res[0])
|
|
return;
|
|
this.canvas = res[0].node;
|
|
this.ctx = res[0].node.getContext("2d");
|
|
this.dpr = common_vendor.index.getSystemInfoSync().pixelRatio;
|
|
this.updateCanvasSize();
|
|
if (this.imgUrl) {
|
|
await this.loadImage(this.imgUrl);
|
|
}
|
|
});
|
|
},
|
|
updateCanvasSize() {
|
|
this.canvasDisplayWidth = this.width;
|
|
this.canvasDisplayHeight = this.height;
|
|
this.canvasActualWidth = this.width * this.dpr;
|
|
this.canvasActualHeight = this.height * this.dpr;
|
|
if (this.canvas) {
|
|
this.canvas.width = this.canvasActualWidth;
|
|
this.canvas.height = this.canvasActualHeight;
|
|
this.ctx.scale(this.dpr, this.dpr);
|
|
this.redraw();
|
|
}
|
|
},
|
|
async loadImage(src) {
|
|
try {
|
|
this.image = await new Promise((resolve, reject) => {
|
|
const image = this.canvas.createImage();
|
|
image.src = src;
|
|
image.onload = () => resolve(image);
|
|
image.onerror = reject;
|
|
});
|
|
this.redraw();
|
|
} catch (e) {
|
|
common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:125", "图片加载失败:", e);
|
|
this.image = null;
|
|
this.redraw();
|
|
}
|
|
},
|
|
redraw() {
|
|
if (!this.ctx)
|
|
return;
|
|
this.ctx.save();
|
|
this.ctx.resetTransform();
|
|
this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight);
|
|
this.ctx.scale(this.dpr, this.dpr);
|
|
const { a, b, c, d, tx, ty } = this.matrix;
|
|
this.ctx.setTransform(a, b, c, d, tx, ty);
|
|
if (this.image) {
|
|
this.ctx.drawImage(
|
|
this.image,
|
|
0,
|
|
0,
|
|
this.canvasDisplayWidth,
|
|
this.canvasDisplayHeight
|
|
);
|
|
} else {
|
|
this.ctx.fillStyle = "#f0f0f0";
|
|
this.ctx.fillRect(0, 0, this.width, this.height);
|
|
this.ctx.fillStyle = "#999";
|
|
this.ctx.textAlign = "center";
|
|
this.ctx.textBaseline = "middle";
|
|
this.ctx.fillText("图片加载失败", this.width / 2, this.height / 2);
|
|
}
|
|
this.ctx.restore();
|
|
}
|
|
}
|
|
};
|
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
return {
|
|
a: `${$data.canvasDisplayWidth}px`,
|
|
b: `${$data.canvasDisplayHeight}px`
|
|
};
|
|
}
|
|
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
|
wx.createComponent(Component);
|
|
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/index/transform-canvas.js.map
|