场景是这样,一张整图切割成3x3的九宫格依次drawImage,实现一个拼图游戏。但是有这样一个问题,就是首次加载页面drawImage后toDataURL的值必定是data:,但是只要加载过一次有了缓存,就不出现这种情况了,这个要怎么解决。
这些事件我都是放在image.onload后的,确定已经加载好了图片
<template>
<div class="jigsaw" @touchmove.prevent>
<canvas
v-show="false"
ref="canvasRef"
class="jigsaw-canvas"
width="80"
:height="canvasHeight"
></canvas>
<div class="jigsaw-sudoku" ref="sudokuRef">
<img :src="imgSrc" alt class="jigsaw-sudoku-reference" />
<div class="jigsaw-sudoku-container">
<div
v-for="(item, index) in 9"
:key="`sudoku_${index}`"
class="jigsaw-sudoku-container-groove"
>
<img ref="sudokuItemRef" :id="`_${index}`" src="@/assets/cover.png" alt />
</div>
</div>
</div>
<ul class="jigsaw-selector" id="selector" ref="selectorRef">
<li v-for="(item, index) in 9" :key="`selector_${index}`">
<img ref="selectorItemRef" src alt draggable />
</li>
</ul>
<button v-if="showStartButton" @click="actionToStart">开始</button>
<div>用时:{{ differenceTime }}</div>
</div>
</template>
<script>
import { polyfill } from 'mobile-drag-drop';
import { scrollBehaviourDragImageTranslateOverride } from 'mobile-drag-drop/scroll-behaviour';
export default {
name: '',
props: {},
data() {
return {
imgSrc: require('@/assets/jigsaw.jpeg'),
pieceWidth: 1, // 切片宽度
pieceHeight: 1, // 切片高度
ctx: undefined,
selectorList: [],
selectorArr: [],
showStartButton: true,
isCompleted: false,
startDate: undefined,
endDate: undefined,
differenceTime: 0,
};
},
computed: {
canvasHeight () {
return 80 * this.pieceHeight / this.pieceWidth
}
},
created() {},
mounted() {
// 移动端适配
polyfill({
dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride,
});
this.onToInit();
},
watch: {},
methods: {
/* ----------------------行为触发函数------------------------ */
// 开始拼图
actionToStart() {
this.showStartButton = false;
this.startData = new Date().getTime();
},
// 结束拼图
actionToComplete() {
this.endDate = new Date().getTime();
this.differenceTime = this.endDate - this.startData;
},
/* ----------------------内部处理函数------------------------ */
// 初始化随机
onToRandomImage() {
this.selectorArr.sort(() => Math.random() - 0.5);
},
// 原图切片
async onToRenderImage(image) {
let index = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
console.log(this.$refs.canvasRef.width, this.$refs.canvasRef.height)
this.ctx.drawImage(
image,
this.pieceWidth * 2 * j,
this.pieceHeight * 2 * i,
this.pieceWidth * 2,
this.pieceHeight * 2,
0,
0,
this.pieceWidth,
this.pieceHeight,
);
this.selectorArr[index].src = this.$refs.canvasRef.toDataURL('image/jpeg');
this.selectorArr[index].id = index;
index++;
}
}
},
// 拖动相关事件处理
onToDrag() {
const sudoku = this.$refs.sudokuRef;
const selector = this.$refs.selectorRef;
const _this = this;
sudoku.addEventListener(
'dragover',
function(e) {
e.preventDefault();
},
false,
);
sudoku.addEventListener(
'dragenter',
function(e) {
e.preventDefault();
},
false,
);
selector.addEventListener(
'dragstart',
function(e) {
const target = e.target;
if (target.tagName.toLowerCase() == 'img') {
e.dataTransfer.setData('id', target.id);
}
},
false,
);
sudoku.addEventListener(
'drop',
function(e) {
const target = e.target;
if (target.tagName.toLowerCase() == 'img') {
const originObj = document.getElementById(e.dataTransfer.getData('id'));
const endObj = target;
if (target.id === `_${e.dataTransfer.getData('id')}`) {
[endObj.src, endObj.id, originObj.id] = [originObj.src, originObj.id, endObj.id];
// 隐藏选项,不直接移除是为了保留内容撑开父高度
originObj.parentNode.style.width = 0;
originObj.parentNode.style.opacity = 0;
originObj.parentNode.style.zIndex = -1;
originObj.parentNode.style.margin = 0;
// 判断进度
const imageSequence = _this.$refs.sudokuItemRef;
let arr = [];
for (let i = 0; i < 9; i++) {
arr.push(imageSequence[i].id);
}
if (arr.toString() === ['0', '1', '2', '3', '4', '5', '6', '7', '8'].toString()) {
_this.isCompleted = true;
_this.actionToComplete();
}
}
}
},
false,
);
},
// 加载原图
onToLoadImage(imgSrc) {
const image = new Image();
image.src = imgSrc;
this.pieceWidth = image.width / 6;
this.pieceHeight = image.height / 6;
image.onload = () => {
this.onToRandomImage();
this.onToRenderImage(image);
this.onToDrag();
};
},
// 初始化
onToInit() {
this.ctx = this.$refs.canvasRef.getContext('2d');
this.selectorList = this.$refs.selectorItemRef;
this.selectorArr = Array.from(this.selectorList);
this.onToLoadImage(this.imgSrc);
},
/* ----------------------请求调用函数------------------------ */
// 完成拼图,提交结果
ajaxToSubmit() {},
},
components: {},
};
</script>
<style lang="less" scoped>
.jigsaw {
&-sudoku {
width: 246px;
margin: 80px auto;
overflow: hidden;
position: relative;
&-reference {
width: 100%;
object-fit: contain;
}
&-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
&-groove {
border: 1px solid #fff;
> img {
width: 100%;
height: 100%;
}
}
}
}
&-selector {
display: flex;
overflow-x: auto;
> li {
width: 80px;
margin: 1px;
position: relative;
transition: all 0.3s ease-in;
> img {
width: 80px;
object-fit: contain;
}
}
}
}
</style>
其中cover.png只是一张半透明的黑块,用来做蒙层的
在 https://www.w3school.com.cn/t... 这里,我写了一段代码来测试……
完全没有问题啊,所以我也不知道你到底遇到了啥问题。