Parent Component for Image Upload
Create an upload button that trigegrs the file selection dialog:
uni.chooseMessageFile({
extension: [".jpg", ".png", ".jpeg"],
success: (res) => {
const paths = res.tempFiles.map((item) => item.path);
uni.navigateTo({
url: `/pages/document/detail?files=${paths}`,
});
},
});
Image Splittnig Page Component
<template>
<view class="container">
<view v-for="(item, index) in files" :key="index">
<imageCutting :imgSrc="item" :currenIndex="index" ref="printRefs" />
</view>
<button @click="splitImageButtonClick">分割图片</button>
</view>
</template>
<script>
import imageCutting from "./print.vue";
export default {
components: {
imageCutting,
},
data() {
return {
files: [],
splitResults: [],
};
},
onLoad(option) {
this.files = option.files.split(",");
},
methods: {
splitImageButtonClick() {
this.splitResults = [];
const promises = this.$refs.printRefs.map((item) => {
return new Promise((resolve) => {
item.splitImage((leftImagePath, rightImagePath) => {
this.splitResults.push({
left: leftImagePath,
right: rightImagePath,
});
resolve();
});
});
});
Promise.all(promises).then(() => {
console.log("分割完成", this.splitResults);
});
},
},
};
</script>
ImageCutting Component
<template>
<view class="container">
<view
class="canvas-container"
@touchstart="touchStart"
@touchmove="touchMove"
>
<image
class="main-image"
mode="widthFix"
:src="imgSrc"
@load="onImageLoad"
></image>
<view class="divider" :style="{ left: lineX + 'px' }"></view>
</view>
<view class="count-print">
<text>第{{ currenIndex * 2 + 1 }}页</text>
<text>第{{ currenIndex * 2 + 2 }}页</text>
</view>
</view>
</template>
<script>
export default {
props: {
imgSrc: {
default: "",
type: String,
},
currenIndex: {
default: 0,
type: Number,
},
},
data() {
return {
deviceWidth: uni.getSystemInfoSync().windowWidth,
lineX: uni.getSystemInfoSync().windowWidth * 0.5,
imageWidth: 0,
imageHeight: 0,
startX: 0,
};
},
methods: {
splitImage(callback) {
const drp = uni.getWindowInfo().pixelRatio;
const canvasLeft = uni.createOffscreenCanvas({ type: "2d" });
const ctxLeft = canvasLeft.getContext("2d");
const canvasRight = uni.createOffscreenCanvas({ type: "2d" });
const ctxRight = canvasRight.getContext("2d");
const displayWidth = this.imageWidth / drp;
const displayHeight = this.imageHeight / drp;
const splitPosition = (this.lineX / this.deviceWidth) * displayWidth;
const canvasLeftWidth = splitPosition * drp;
const canvasLeftHeight = displayHeight * drp;
canvasLeft.width = canvasLeftWidth;
canvasLeft.height = canvasLeftHeight;
const canvasRightWidth = (displayWidth - splitPosition) * drp;
canvasRight.width = canvasRightWidth;
canvasRight.height = canvasLeftHeight;
const image = canvasLeft.createImage();
image.src = this.imgSrc;
image.onload = () => {
ctxLeft.drawImage(
image,
0,
0,
canvasLeftWidth,
canvasLeftHeight,
0,
0,
canvasLeftWidth,
canvasLeftHeight
);
ctxRight.drawImage(
image,
canvasLeftWidth,
0,
canvasRightWidth,
canvasLeftHeight,
0,
0,
canvasRightWidth,
canvasLeftHeight
);
uni.canvasToTempFilePath({
canvas: canvasLeft,
success: (res) => {
const leftImagePath = res.tempFilePath;
uni.canvasToTempFilePath({
canvas: canvasRight,
success: (res) => {
const rightImagePath = res.tempFilePath;
callback(leftImagePath, rightImagePath);
},
});
},
});
};
},
touchStart(event) {
this.startX = event.touches[0].clientX;
},
touchMove(event) {
const moveX = event.touches[0].clientX - this.startX;
this.startX = event.touches[0].clientX;
this.lineX = Math.min(
Math.max(0, this.lineX + moveX),
this.deviceWidth - 2
);
},
onImageLoad(event) {
const imageInfo = event.detail;
this.imageWidth = imageInfo.width;
this.imageHeight = imageInfo.height;
},
},
};
</script>
<style lang="scss" scoped>
.main-image {
width: 100%;
vertical-align: bottom;
}
.canvas-container {
position: relative;
border: 2rpx solid #efefef;
}
.divider {
position: absolute;
top: 0;
bottom: 0;
border-left: 4rpx dashed #f00;
height: 100%;
z-index: 10;
}
.count-print {
display: flex;
justify-content: space-around;
margin: 40rpx 0;
}
</style>
Handling Canvas Errors
If encountering canvasToTempFilePath:fail invalid viewId or Cannot read property 'apply' of undefined, replace the nested canvasToTempFilePath calls with toDataURL():
callback(canvasLeft.toDataURL(), canvasRight.toDataURL());