我想在表格单元格中放置一些签名板。
但是仅绘制第一个画布,而其他不绘制。 我检查了鼠标/触摸事件。 它被触发(上/下/移动)并调用了draw函数,但未绘制canvas。
我检查了toDataURL,结果只是白色图像。
桌子外面的帆布很好。绘制效果很好。
我找不到与此相关的文档。请帮助我。
这是代码。
// this is draw function
const init = function (el) {
let context = el.getContext("2d");
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 2;
let offset = {
left: el.offsetLeft,
top: el.offsetTop,
}
let down = false
let points = []
function draw() {
context.beginPath();
for (let i = 0; i < points.length - 1; i++) {
const p = points[i]
const pn = points[i + 1]
if (pn.x === p.x && p.y === pn.y && p.first && pn.last) {
context.arc(pn.x, pn.y, 1, 0, 2 * Math.PI);
context.fill()
} else {
context.moveTo(p.x, p.y)
context.lineTo(pn.x, pn.y)
}
}
context.stroke();
context.closePath();
}
function addPoint(ev, setting) {
setting = setting || {}
let p = {
x: event.pageX - offset.left,
y: event.pageY - offset.top,
...setting,
}
points.push(p)
}
function down_handler(event) {
down = true
addPoint(event, {first: true})
event.preventDefault()
}
function move_handler(event) {
if (!down) {
return
}
addPoint(event, {drag: true})
draw()
event.preventDefault()
}
function up_handler(event) {
down = false
addPoint(event, {last: true})
draw()
points.splice(0, points.length)
event.preventDefault()
}
el.addEventListener("pointerdown", down_handler, false);
el.addEventListener("pointermove", move_handler, false);
el.addEventListener("pointerup", up_handler, false);
el.style['touch-action'] = 'none'
}
Vue.component('signature', {
props: {
width: {
type: Number,
required: true,
},
height: {
type: Number,
required: true,
},
customStyle: {
type: Object,
default() {
return {}
},
},
},
mounted() {
init(this.$refs.signaturePadCanvas)
},
render(createElement) {
const {width, height, customStyle} = this;
return createElement(
'div',
{
style: {
width: `${width}px`,
height: `${height}px`,
...customStyle,
},
},
[
createElement('canvas', {
attrs: {
width: width,
height: height,
},
style: {
width: '100%',
height: '100%',
'touch-action': 'none',
'background': 'gray',
},
ref: 'signaturePadCanvas',
}),
],
);
},
})
new Vue({
el: '#app',
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
</tr>
<tr>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
</tr>
</table>
<signature :width="200" :height="200"></signature>
<signature :width="200" :height="200"></signature>
</div>
答案 0 :(得分:1)
那是抵销问题。
我只是得到画布的偏移坐标,但是describe the border box of an element relative to the offsetParent.
下面是固定代码。
// this is draw function
const init = function (el) {
let context = el.getContext("2d");
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 2;
let clientRect = el.getClientRects()
let offset = {
left : clientRect[0].left,
top : clientRect[0].top,
}
let down = false
let points = []
function draw() {
context.beginPath();
for (let i = 0; i < points.length - 1; i++) {
const p = points[i]
const pn = points[i + 1]
if (pn.x === p.x && p.y === pn.y && p.first && pn.last) {
context.arc(pn.x, pn.y, 1, 0, 2 * Math.PI);
context.fill()
} else {
context.moveTo(p.x, p.y)
context.lineTo(pn.x, pn.y)
}
}
context.stroke();
context.closePath();
}
function addPoint(ev, setting) {
setting = setting || {}
let p = {
x: ev.clientX - offset.left,
y: ev.clientY - offset.top,
...setting,
}
points.push(p)
}
function down_handler(event) {
down = true
addPoint(event, {first: true})
event.preventDefault()
}
function move_handler(event) {
if (!down) {
return
}
addPoint(event, {drag: true})
draw()
event.preventDefault()
}
function up_handler(event) {
down = false
addPoint(event, {last: true})
draw()
points.splice(0, points.length)
event.preventDefault()
}
el.addEventListener("pointerdown", down_handler, false);
el.addEventListener("pointermove", move_handler, false);
el.addEventListener("pointerup", up_handler, false);
el.style['touch-action'] = 'none'
}
Vue.component('signature', {
props: {
width: {
type: Number,
required: true,
},
height: {
type: Number,
required: true,
},
customStyle: {
type: Object,
default() {
return {}
},
},
},
mounted() {
init(this.$refs.signaturePadCanvas)
},
render(createElement) {
const {width, height, customStyle} = this;
return createElement(
'div',
{
style: {
width: `${width}px`,
height: `${height}px`,
...customStyle,
},
},
[
createElement('canvas', {
attrs: {
width: width,
height: height,
},
style: {
width: '100%',
height: '100%',
'touch-action': 'none',
'background': 'gray',
},
ref: 'signaturePadCanvas',
}),
],
);
},
})
new Vue({
el: '#app',
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
</tr>
<tr>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
<td>
<signature :width="200" :height="200"></signature>
</td>
</tr>
</table>
<signature :width="200" :height="200"></signature>
<signature :width="200" :height="200"></signature>
</div>