background needs
When I was working on a small program, I encountered a scene where the user took a photo => intelligently parsed the topic => the page echoed the frame selection
After echoing, it may not be a certain area or a certain question that the user wants, and in this case, the user needs to manually edit and crop. First look at the picture effect and video demonstration
After reading, let's analyze
When I was doing it, my first reaction was the combination of canvas and movable-area, but no matter how I tried, it didn't work. Then I went to Baidu to check, all kinds of miscellaneous things did not achieve the effect I wanted to achieve. Then I asked the big guy who had done it before, and the answer he gave was the combination of vanvas and movable-area
Let’s talk about the issue of frame selection echo first.
misunderstanding
Dynamically obtain the size of the picture box and then compare it with the size of the mobile phone screen to get the ratio Draw all the frame selection positions according to the returned coordinate point * ratio
correct
Dynamically obtain the height of the box (for subsequent cropping) and assign the operation of placing the picture box to the Image operation
Look at the code on the next page
<view v-if="vdata.selectBox" class="photographMain">
<view class="swiperMain">
<view class="handelImg" v-if="!vdata.imgList.length">
<nut-button loading type="warning"></nut-button>
<view>图片处理中</view>
</view>
<swiper
v-else
@change="getCurrent"
class="swiper"
indicator-color="#999"
indicator-active-color="#333"
:circular="false"
:indicator-dots="false"
:current="vdata.current - 1"
>
<swiper-item v-for="(item, i) in vdata.imgList" :key="i">
<view class="list-item">
<image :src="item.originUrl" class="imageContent" :mode="computedFixed">
<view class="mc">
<template v-if="item.contentListInfoList && item.contentListInfoList.length">
<view
class="mc-item"
v-for="(bg, key) in item.contentListInfoList"
:style="handlePosition(item, bg.point2dXYList)"
:key="key"
>
<view class="bj" @tap="editBox(item, bg.point2dXYList, bg)">编辑</view>
<view class="jj" v-show="!bg.isCheck">
<image
@tap="changeIsCheck(i, key, true)"
src="https://dcg-c-system.obs.cn-east-3.myhuaweicloud.com/ctb/69ddc2a38118419eb6815bb37f6fee70/addPot.png"
mode="scaleToFill"
/>
</view>
<view class="jy" v-show="bg.isCheck">
<image
@tap="changeIsCheck(i, key, false)"
src="https://dcg-c-system.obs.cn-east-3.myhuaweicloud.com/ctb/5fb2d6d087aa44b1b42c405f364610ca/commit.png"
mode="scaleToFill"
/>
</view>
</view>
</template>
</view>
</image>
</view>
</swiper-item>
</swiper>
<view class="current"> {
{ vdata.current }}/{
{ vdata.imgUrl.length }} </view>
</view>
</view>
<view v-else class="welMain">
<welCropper @cropdown="cropdown" :cropperOptions="vdata.cropperOptions" />
</view>
Then look at welCropper has two versions, one vue version and one react version
Take the vue version as an example
<template>
<scroll-view :class="['cropper_main_container', data.cropperData.hidden ? 'hidden' : '']">
<view
class="cropper_container"
:style="{ width: data.cropperData.W + 'px', height: data.cropperData.H + 'px' }"
>
<canvas
class="original_canvas"
canvas-id="originalCanvas"
:style="{
width: data.changableData.originalSize.width + 'px',
height: data.changableData.originalSize.height + 'px',
}"
></canvas>
<image
:src="data.cropperData.imageInfo.path"
class="scale-image cropper_canvas_container_item"
mode="aspectFill"
:style="{
left: data.changableData.previewImageInfo.x + 'px',
top: data.changableData.previewImageInfo.y + 'px',
width: data.changableData.previewImageInfo.w + 'px',
height: data.changableData.previewImageInfo.h + 'px',
transform: `rotate(${data.changableData.rotateDegree}deg)`,
}"
></image>
<!-- transform:rotate() -->
<view
:class="['cropper_canvas_container', data.cropperData.canvasType ? 'isOpacity' : '']"
:style="{
width: data.changableData.scaleSize.width + 'px',
height: data.changableData.scaleSize.height + 'px',
}"
>
<canvas
:type="data.cropperData.canvasType || ''"
:canvas-id="data.canvasId"
class="move_canvas cropper_canvas_container_item"
></canvas>
<template v-if="data.cropperData.drawSign == 1">
<movable-area
class="cropper_movable_area_container"
:style="{
width: data.changableData.scaleSize.width + 'px',
height: data.changableData.scaleSize.height + 'px',
}"
>
<template v-if="data.moveItems">
<template v-for="(item, i) in data.moveItems" :key="i">
<movable-view
class="move_item"
:style="{
width: data.cropperData.itemLength + 'px',
height: data.cropperData.itemLength + 'px',
}"
direction="all"
:x="item.x - data.cropperData.itemLength / 2"
:y="item.y - data.cropperData.itemLength / 2"
@touchmove="moveEvent"
@touchend="endEvent"
@touchcancel="touchcancelEvent"
:data-key="i"
></movable-view>
</template>
</template>
</movable-area>
</template>
<template v-else>
<movable-area
class="cropper_movable_area_container"
:style="{
width: data.changableData.scaleSize.width + 'px',
height: data.changableData.scaleSize.height + 'px',
}"
>
<template v-if="data.moveItems">
<template v-for="(item, i) in data.moveItems" :key="i">
<movable-view
class="move_item"
style="width:{
{data.cropperData.itemLength}}px; height:{
{data.cropperData.itemLength}}px;"
direction="all"
:x="item.x - data.cropperData.itemLength / 2"
:y="item.y - data.cropperData.itemLength / 2"
@touchmove="moveEvent"
@touchend="endEvent"
@touchcancel="touchcancelEvent"
data-key="{
{index}}"
></movable-view>
</template>
</template>
</movable-area>
</template>
</view>
</view>
</scroll-view>
</template>
Pitfalls encountered and precautions
1. When packaging components, the peripheral box should be positioned
2. When moving, there is a deviation in the moving point (here is 100% scaled if the custom navbar needs to subtract all other padding, margin, height)
3. If a page is used repeatedly, an error will be reported (canvas id has been used and cannot be used again) Dynamically set cancasId
4. Box selection echo, the coordinate point position is deviated (always keep the image size in the same proportion to scale the echo coordinates can not use px, it is better to use %)
5. When the height is obtained through createSelectorQuery, the setting of setTimerOut is not obtained
This is all the template code of welCropper. You can try to reverse the logic based on the code. Interested friends can private message me or add wx: Darren_jm Remark csdn to get all the code