fix
This commit is contained in:
parent
94e79c4b77
commit
a99e07d5fb
@ -18,6 +18,7 @@
|
|||||||
:width="canvasWidth"
|
:width="canvasWidth"
|
||||||
:height="canvasHeight"
|
:height="canvasHeight"
|
||||||
:matrix="transformMatrix"
|
:matrix="transformMatrix"
|
||||||
|
:imgUrl="'https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg'"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -220,7 +221,7 @@ export default {
|
|||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const canvas = this.$refs.canvasRef;
|
const canvas = this.$refs.canvasRef;
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
canvas.draw();
|
// canvas.draw();
|
||||||
|
|
||||||
// 计算当前缩放值
|
// 计算当前缩放值
|
||||||
this.scaleValue = Math.sqrt(
|
this.scaleValue = Math.sqrt(
|
||||||
|
@ -1,154 +1,172 @@
|
|||||||
|
<!-- 子组件 transform-canvas.vue -->
|
||||||
<template>
|
<template>
|
||||||
<canvas
|
<view>
|
||||||
canvas-id="gestureCanvas"
|
<canvas
|
||||||
:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
|
id="myCanvas"
|
||||||
/>
|
canvas-id="myCanvas"
|
||||||
|
type="2d"
|
||||||
|
:style="{
|
||||||
|
width: `${canvasDisplayWidth}px`,
|
||||||
|
height: `${canvasDisplayHeight}px`,
|
||||||
|
border: '1px solid #eee'
|
||||||
|
}"
|
||||||
|
></canvas>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
width: Number,
|
width: Number, // 画布实际宽度(像素)
|
||||||
height: Number,
|
height: Number, // 画布实际高度(像素)
|
||||||
matrix: Object
|
imgUrl: String, // 图片URL
|
||||||
|
matrix: { // 变换矩阵
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
ctx: null,
|
canvasContext: null,
|
||||||
canvasWidth: this.width,
|
image: null,
|
||||||
canvasHeight: this.height
|
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() {
|
mounted() {
|
||||||
this.initCanvas();
|
this.initCanvas();
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
initCanvas() {
|
initCanvas() {
|
||||||
this.ctx = uni.createCanvasContext('gestureCanvas', this);
|
const query = uni.createSelectorQuery().in(this);
|
||||||
const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
query.select('#myCanvas')
|
||||||
this.ctx.scale(pixelRatio, pixelRatio);
|
.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 = uni.getSystemInfoSync().pixelRatio;
|
||||||
|
|
||||||
|
// 更新画布尺寸
|
||||||
|
this.updateCanvasSize();
|
||||||
|
|
||||||
|
// 如果已有图片URL,加载图片
|
||||||
|
if (this.imgUrl) {
|
||||||
|
await this.loadImage(this.imgUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
applyTransform(matrix) {
|
updateCanvasSize() {
|
||||||
if (!matrix) return;
|
// 显示尺寸使用prop传入的width/height
|
||||||
|
this.canvasDisplayWidth = this.width;
|
||||||
|
this.canvasDisplayHeight = this.height;
|
||||||
|
|
||||||
// 核心修复:考虑像素比的转换
|
// 实际像素尺寸考虑DPR
|
||||||
const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
this.canvasActualWidth = this.width * this.dpr;
|
||||||
const tx = matrix.tx * pixelRatio;
|
this.canvasActualHeight = this.height * this.dpr;
|
||||||
const ty = matrix.ty * pixelRatio;
|
|
||||||
|
|
||||||
// 直接设置完整的变换矩阵
|
if (this.canvas) {
|
||||||
this.ctx.setTransform(
|
this.canvas.width = this.canvasActualWidth;
|
||||||
matrix.a,
|
this.canvas.height = this.canvasActualHeight;
|
||||||
matrix.b,
|
this.ctx.scale(this.dpr, this.dpr);
|
||||||
matrix.c,
|
this.redraw();
|
||||||
matrix.d,
|
}
|
||||||
tx,
|
|
||||||
ty
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 调试网格
|
async loadImage(src) {
|
||||||
// drawDebugGrid() {
|
try {
|
||||||
// if (!this.ctx) return;
|
this.image = await new Promise((resolve, reject) => {
|
||||||
|
const image = this.canvas.createImage();
|
||||||
// const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
image.src = src;
|
||||||
// const width = this.canvasWidth * pixelRatio;
|
image.onload = () => resolve(image);
|
||||||
// const height = this.canvasHeight * pixelRatio;
|
image.onerror = reject;
|
||||||
|
});
|
||||||
// // 保存当前状态
|
this.redraw();
|
||||||
// this.ctx.save();
|
} catch (e) {
|
||||||
|
console.error("图片加载失败:", e);
|
||||||
// // 重置变换
|
this.image = null;
|
||||||
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
this.redraw(); // 加载失败时也需要重绘画布
|
||||||
|
}
|
||||||
// // 绘制网格
|
},
|
||||||
// this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)';
|
|
||||||
// this.ctx.lineWidth = 1;
|
|
||||||
|
|
||||||
// // 横向线
|
|
||||||
// for (let y = 0; y <= height; y += 50) {
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, y);
|
|
||||||
// this.ctx.lineTo(width, y);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 纵向线
|
|
||||||
// for (let x = 0; x <= width; x += 50) {
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(x, 0);
|
|
||||||
// this.ctx.lineTo(x, height);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 绘制坐标轴
|
|
||||||
// this.ctx.strokeStyle = '#ff0000';
|
|
||||||
// this.ctx.lineWidth = 2;
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, 0);
|
|
||||||
// this.ctx.lineTo(width, 0);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, 0);
|
|
||||||
// this.ctx.lineTo(0, height);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
|
|
||||||
// // 恢复之前的状态
|
|
||||||
// this.ctx.restore();
|
|
||||||
|
|
||||||
// this.ctx.draw();
|
|
||||||
// },
|
|
||||||
|
|
||||||
// 绘制主内容
|
redraw() {
|
||||||
draw() {
|
if (!this.ctx) return;
|
||||||
if (!this.ctx) {
|
|
||||||
console.warn('Canvas上下文未初始化');
|
// 保存当前状态
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 清除Canvas
|
// 恢复上下文状态
|
||||||
this.clearCanvas();
|
this.ctx.restore();
|
||||||
|
|
||||||
// 2. 应用当前变换
|
|
||||||
this.applyTransform(this.matrix);
|
|
||||||
|
|
||||||
// 3. 绘制内容
|
|
||||||
this.drawContent();
|
|
||||||
},
|
|
||||||
|
|
||||||
clearCanvas() {
|
|
||||||
const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
|
||||||
const width = this.canvasWidth * pixelRatio;
|
|
||||||
const height = this.canvasHeight * pixelRatio;
|
|
||||||
|
|
||||||
// 重置变换
|
|
||||||
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
||||||
this.ctx.clearRect(0, 0, width, height);
|
|
||||||
},
|
|
||||||
|
|
||||||
drawContent() {
|
|
||||||
// 绘制一个矩形和圆形
|
|
||||||
this.ctx.fillStyle = '#3498db';
|
|
||||||
this.ctx.fillRect(50, 50, 100, 100);
|
|
||||||
|
|
||||||
this.ctx.fillStyle = '#e74c3c';
|
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.arc(150, 150, 50, 0, 2 * Math.PI);
|
|
||||||
this.ctx.fill();
|
|
||||||
|
|
||||||
// 绘制一个文字
|
|
||||||
this.ctx.fillStyle = '#2c3e50';
|
|
||||||
this.ctx.font = '20px sans-serif';
|
|
||||||
this.ctx.fillText('手势Canvas', 50, 250);
|
|
||||||
|
|
||||||
// 执行绘制
|
|
||||||
this.ctx.draw();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
@ -1 +1 @@
|
|||||||
{"version":3,"file":"transform-canvas.js","sources":["/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue?type=component"],"sourcesContent":["import Component from '/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue'\nwx.createComponent(Component)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,gBAAgB,SAAS;"}
|
{"version":3,"file":"transform-canvas.js","sources":["/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue?type=component"],"sourcesContent":["import Component from '/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue'\nwx.createComponent(Component)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,gBAAgB,SAAS;"}
|
@ -6882,7 +6882,7 @@ function initOnError() {
|
|||||||
function initRuntimeSocketService() {
|
function initRuntimeSocketService() {
|
||||||
const hosts = "127.0.0.1,172.10.0.205";
|
const hosts = "127.0.0.1,172.10.0.205";
|
||||||
const port = "8090";
|
const port = "8090";
|
||||||
const id = "mp-weixin_aMdMwA";
|
const id = "mp-weixin_Z7-NJ2";
|
||||||
const lazy = typeof swan !== "undefined";
|
const lazy = typeof swan !== "undefined";
|
||||||
let restoreError = lazy ? () => {
|
let restoreError = lazy ? () => {
|
||||||
} : initOnError();
|
} : initOnError();
|
||||||
|
@ -35,7 +35,7 @@ const _sfc_main = {
|
|||||||
container: this.containerRect
|
container: this.containerRect
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:76", "手势处理器初始化失败:", e);
|
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:77", "手势处理器初始化失败:", e);
|
||||||
this.gestureHandler = {
|
this.gestureHandler = {
|
||||||
catchEvent: (event) => {
|
catchEvent: (event) => {
|
||||||
if (event.touches.length > 0) {
|
if (event.touches.length > 0) {
|
||||||
@ -72,21 +72,21 @@ const _sfc_main = {
|
|||||||
width: rect.width,
|
width: rect.width,
|
||||||
height: rect.height
|
height: rect.height
|
||||||
};
|
};
|
||||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:123", "成功获取容器位置:", this.containerRect);
|
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:124", "成功获取容器位置:", this.containerRect);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:127", "获取容器位置失败:", e);
|
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:128", "获取容器位置失败:", e);
|
||||||
}
|
}
|
||||||
await new Promise((r) => setTimeout(r, 100));
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
retryCount++;
|
retryCount++;
|
||||||
}
|
}
|
||||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:135", `容器位置获取失败,已重试${maxRetries}次`);
|
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:136", `容器位置获取失败,已重试${maxRetries}次`);
|
||||||
},
|
},
|
||||||
// 事件处理
|
// 事件处理
|
||||||
async handleTouchEvent(event) {
|
async handleTouchEvent(event) {
|
||||||
if (!this.gestureHandler || !this.containerRect) {
|
if (!this.gestureHandler || !this.containerRect) {
|
||||||
common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:141", "手势处理器未就绪,尝试重新初始化...");
|
common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:142", "手势处理器未就绪,尝试重新初始化...");
|
||||||
await this.getContainerPosition();
|
await this.getContainerPosition();
|
||||||
this.initGestureHandler();
|
this.initGestureHandler();
|
||||||
if (event.type === "touchend" || event.type === "touchcancel") {
|
if (event.type === "touchend" || event.type === "touchcancel") {
|
||||||
@ -113,7 +113,7 @@ const _sfc_main = {
|
|||||||
const correctedTouches = Array.from(event.touches).map((touch) => {
|
const correctedTouches = Array.from(event.touches).map((touch) => {
|
||||||
const x = touch.clientX - this.containerRect.left;
|
const x = touch.clientX - this.containerRect.left;
|
||||||
const y = touch.clientY - this.containerRect.top;
|
const y = touch.clientY - this.containerRect.top;
|
||||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:181", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`);
|
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:182", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`);
|
||||||
return {
|
return {
|
||||||
...touch,
|
...touch,
|
||||||
x,
|
x,
|
||||||
@ -143,7 +143,6 @@ const _sfc_main = {
|
|||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const canvas = this.$refs.canvasRef;
|
const canvas = this.$refs.canvasRef;
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
canvas.draw();
|
|
||||||
this.scaleValue = Math.sqrt(
|
this.scaleValue = Math.sqrt(
|
||||||
this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b
|
this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b
|
||||||
);
|
);
|
||||||
@ -184,7 +183,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|||||||
g: common_vendor.p({
|
g: common_vendor.p({
|
||||||
width: $data.canvasWidth,
|
width: $data.canvasWidth,
|
||||||
height: $data.canvasHeight,
|
height: $data.canvasHeight,
|
||||||
matrix: $data.transformMatrix
|
matrix: $data.transformMatrix,
|
||||||
|
imgUrl: "https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg"
|
||||||
}),
|
}),
|
||||||
h: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
h: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
||||||
i: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
i: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
||||||
|
@ -3,117 +3,146 @@ const common_vendor = require("../../common/vendor.js");
|
|||||||
const _sfc_main = {
|
const _sfc_main = {
|
||||||
props: {
|
props: {
|
||||||
width: Number,
|
width: Number,
|
||||||
|
// 画布实际宽度(像素)
|
||||||
height: Number,
|
height: Number,
|
||||||
matrix: Object
|
// 画布实际高度(像素)
|
||||||
|
imgUrl: String,
|
||||||
|
// 图片URL
|
||||||
|
matrix: {
|
||||||
|
// 变换矩阵
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
a: 1,
|
||||||
|
b: 0,
|
||||||
|
c: 0,
|
||||||
|
d: 1,
|
||||||
|
tx: 0,
|
||||||
|
ty: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
ctx: null,
|
canvasContext: null,
|
||||||
canvasWidth: this.width,
|
image: null,
|
||||||
canvasHeight: this.height
|
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() {
|
mounted() {
|
||||||
this.initCanvas();
|
this.initCanvas();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initCanvas() {
|
initCanvas() {
|
||||||
this.ctx = common_vendor.index.createCanvasContext("gestureCanvas", this);
|
const query = common_vendor.index.createSelectorQuery().in(this);
|
||||||
const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio;
|
query.select("#myCanvas").fields({ node: true, size: true }).exec(async (res) => {
|
||||||
this.ctx.scale(pixelRatio, pixelRatio);
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
applyTransform(matrix) {
|
updateCanvasSize() {
|
||||||
if (!matrix)
|
this.canvasDisplayWidth = this.width;
|
||||||
return;
|
this.canvasDisplayHeight = this.height;
|
||||||
const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio;
|
this.canvasActualWidth = this.width * this.dpr;
|
||||||
const tx = matrix.tx * pixelRatio;
|
this.canvasActualHeight = this.height * this.dpr;
|
||||||
const ty = matrix.ty * pixelRatio;
|
if (this.canvas) {
|
||||||
this.ctx.setTransform(
|
this.canvas.width = this.canvasActualWidth;
|
||||||
matrix.a,
|
this.canvas.height = this.canvasActualHeight;
|
||||||
matrix.b,
|
this.ctx.scale(this.dpr, this.dpr);
|
||||||
matrix.c,
|
this.redraw();
|
||||||
matrix.d,
|
|
||||||
tx,
|
|
||||||
ty
|
|
||||||
);
|
|
||||||
},
|
|
||||||
// 调试网格
|
|
||||||
// drawDebugGrid() {
|
|
||||||
// if (!this.ctx) return;
|
|
||||||
// const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
|
||||||
// const width = this.canvasWidth * pixelRatio;
|
|
||||||
// const height = this.canvasHeight * pixelRatio;
|
|
||||||
// // 保存当前状态
|
|
||||||
// this.ctx.save();
|
|
||||||
// // 重置变换
|
|
||||||
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
||||||
// // 绘制网格
|
|
||||||
// this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)';
|
|
||||||
// this.ctx.lineWidth = 1;
|
|
||||||
// // 横向线
|
|
||||||
// for (let y = 0; y <= height; y += 50) {
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, y);
|
|
||||||
// this.ctx.lineTo(width, y);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// }
|
|
||||||
// // 纵向线
|
|
||||||
// for (let x = 0; x <= width; x += 50) {
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(x, 0);
|
|
||||||
// this.ctx.lineTo(x, height);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// }
|
|
||||||
// // 绘制坐标轴
|
|
||||||
// this.ctx.strokeStyle = '#ff0000';
|
|
||||||
// this.ctx.lineWidth = 2;
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, 0);
|
|
||||||
// this.ctx.lineTo(width, 0);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(0, 0);
|
|
||||||
// this.ctx.lineTo(0, height);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
// // 恢复之前的状态
|
|
||||||
// this.ctx.restore();
|
|
||||||
// this.ctx.draw();
|
|
||||||
// },
|
|
||||||
// 绘制主内容
|
|
||||||
draw() {
|
|
||||||
if (!this.ctx) {
|
|
||||||
common_vendor.index.__f__("warn", "at pages/index/transform-canvas.vue:110", "Canvas上下文未初始化");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this.clearCanvas();
|
|
||||||
this.applyTransform(this.matrix);
|
|
||||||
this.drawContent();
|
|
||||||
},
|
},
|
||||||
clearCanvas() {
|
async loadImage(src) {
|
||||||
const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio;
|
try {
|
||||||
const width = this.canvasWidth * pixelRatio;
|
this.image = await new Promise((resolve, reject) => {
|
||||||
const height = this.canvasHeight * pixelRatio;
|
const image = this.canvas.createImage();
|
||||||
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
image.src = src;
|
||||||
this.ctx.clearRect(0, 0, width, height);
|
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();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
drawContent() {
|
redraw() {
|
||||||
this.ctx.fillStyle = "#3498db";
|
if (!this.ctx)
|
||||||
this.ctx.fillRect(50, 50, 100, 100);
|
return;
|
||||||
this.ctx.fillStyle = "#e74c3c";
|
this.ctx.save();
|
||||||
this.ctx.beginPath();
|
this.ctx.resetTransform();
|
||||||
this.ctx.arc(150, 150, 50, 0, 2 * Math.PI);
|
this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight);
|
||||||
this.ctx.fill();
|
this.ctx.scale(this.dpr, this.dpr);
|
||||||
this.ctx.fillStyle = "#2c3e50";
|
const { a, b, c, d, tx, ty } = this.matrix;
|
||||||
this.ctx.font = "20px sans-serif";
|
this.ctx.setTransform(a, b, c, d, tx, ty);
|
||||||
this.ctx.fillText("手势Canvas", 50, 250);
|
if (this.image) {
|
||||||
this.ctx.draw();
|
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) {
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||||
return {
|
return {
|
||||||
a: $data.canvasWidth + "px",
|
a: `${$data.canvasDisplayWidth}px`,
|
||||||
b: $data.canvasHeight + "px"
|
b: `${$data.canvasDisplayHeight}px`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||||
|
@ -1 +1 @@
|
|||||||
<canvas canvas-id="gestureCanvas" style="{{'width:' + a + ';' + ('height:' + b)}}"/>
|
<view><canvas id="myCanvas" canvas-id="myCanvas" type="2d" style="{{'width:' + a + ';' + ('height:' + b) + ';' + ('border:' + '1px solid #eee')}}"></canvas></view>
|
Loading…
x
Reference in New Issue
Block a user