Mini program custom drag and crop

 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

View video demo

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

Guess you like

Origin blog.csdn.net/xy19950125/article/details/129712765