總結(jié)一下:
要進(jìn)行海報(bào)繪制離不開(kāi)canvas,我們是先進(jìn)行圖片,文字的拖拽、旋轉(zhuǎn)等操作
最后再對(duì)canvas進(jìn)行繪制,完成海報(bào)繪制。
- 背景區(qū)域設(shè)置為 position: relative,方便圖片在當(dāng)前區(qū)域中拖動(dòng)等處理。
- 添加圖片,監(jiān)聽(tīng)圖片在背景區(qū)域下的 touchstart touchmove touchend 事件
- 拖動(dòng)圖片,在touchmove中,對(duì)圖片進(jìn)行位置(后續(xù)坐標(biāo)-初始坐標(biāo))、角度(勾股定理計(jì)算點(diǎn)到圓心距離,利用角度計(jì)算公式計(jì)算)、放縮比例(勾股定理計(jì)算點(diǎn)到圓心的半徑距離,拖動(dòng)停止的半徑除以初始的半徑,獲得放縮比例scale)的計(jì)算
- 最終canvas繪制,利用dom中的空canvas,將圖片依次繪制到canvas中,并獲取鏈接
部分主要代碼如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-707312.html
const ctx = uni.createCanvasContext("myCanvas", this);
ctx.drawImage(this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
const ctx = uni.createCanvasContext("myCanvas", this);
ctx.drawImage(this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
ctx.save();
ctx.beginPath();
// 畫(huà)背景色(白色)
// ctx.setFillStyle('#fff');
// ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
for (let i=0; i<items.length; i++) {
const cur = items[i]
ctx.save();
ctx.translate(0, 0);
ctx.beginPath();
if(cur.image) {
ctx.translate(cur.x, cur.y); // 圓心坐標(biāo)
ctx.rotate(cur.angle * Math.PI / 180); // 圖片旋轉(zhuǎn)的角度
ctx.translate(-(cur.width * cur.scale / 2), -(cur.height * cur.scale / 2)) // 圖片的縮放
ctx.drawImage(cur.image, 0, 0, cur.width * cur.scale, cur.height * cur.scale); // 圖片繪制
}
if (cur.text) {
ctx.font = `${cur.font}px arial`;
ctx.fillStyle = cur.fillStyle;
ctx.fillText(cur.text, cur.left, cur.top + Number(cur.font));
console.log(cur.left, cur.top + Number(cur.font))
}
ctx.restore();
}
ctx.draw(true, () => {
// 獲取畫(huà)布要裁剪的位置和寬度 均為百分比 * 畫(huà)布中圖片的寬度 保證了在微信小程序中裁剪的圖片模糊 位置不對(duì)的問(wèn)題 canvasT = (this.cutT / this.cropperH) * (this.imageH / pixelRatio)
var canvasW = ((this.cropperW - this.cutL - this.cutR) / this.cropperW) * IMG_REAL_W;
var canvasH = ((this.cropperH - this.cutT - this.cutB) / this.cropperH) * IMG_REAL_H;
var canvasL = (this.cutL / this.cropperW) * IMG_REAL_W;
var canvasT = (this.cutT / this.cropperH) * IMG_REAL_H;
uni.canvasToTempFilePath({
x: canvasL,
y: canvasT,
width: canvasW,
height: canvasH,
// destWidth: canvasW,
// destHeight: canvasH,
quality: +this.quality,
fileType: this.fileType,
canvasId: "myCanvas",
success: (res) => {
uni.hideLoading();
// 成功獲得地址的地方
// this.$emit("getImg", res.tempFilePath);
this.saveImg(res.tempFilePath)
this.isShow = false;
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: "圖片截取失敗!",
icon: "none",
});
},
},
this
);
});
<!-- 海報(bào)背景區(qū)域,采用style動(dòng)態(tài)調(diào)整,cropperInitW,cropperInitH一般為滿屏 -->
<view class="uni-corpper"
:style="'width:' + cropperInitW + 'px;height:' + cropperInitH + 'px;background:#000'">
<!-- 海報(bào)繪制區(qū)域,采用style動(dòng)態(tài)調(diào)整,按照?qǐng)D片的長(zhǎng)寬比例動(dòng)態(tài)計(jì)算 cropperW等-->
<view class="uni-corpper-content" :style="
'width:' +
cropperW +
'px;height:' +
cropperH +
'px;left:' +
cropperL +
'px;top:' +
cropperT +
'px'
">
<!-- 背景圖片區(qū)域 cropperW等同上 -->
<image :src="imageSrc" :style="'width:' + cropperW + 'px;height:' + cropperH + 'px;' + 'border: 3px solid #ff0000;'"></image>
<!-- 海報(bào)上其他圖片處理,for循環(huán),itemList通過(guò)點(diǎn)擊添加 -->
<block v-for="item in itemList" :key="item.id">
<!-- 動(dòng)態(tài)設(shè)置圖片區(qū)域的縮放比例,還有pisition的左右位置,選中時(shí)z-index變大 -->
<view class='touchWrap' :style="{transform: 'scale(' + item.scale + ')', top: item.top + 'px', left: item.left + 'px', 'z-index':item.active ? 100 : 1}">
<view class='imgWrap' :class="item.active ? 'touchActive' : ''" :style="{transform: 'rotate(' + item.angle + 'deg)', border: item.active ? 4 * item.oScale : 0 + 'rpx #fff dashed'}">
<image
v-if="item.image"
:src='item.image'
:style="{width: item.width + 'px', height: item.height + 'px'}"
<!-- 圖片點(diǎn)擊時(shí),記錄點(diǎn)擊圖片當(dāng)前位置 -->
@touchstart="(e) => WraptouchStart(e, item)"
<!-- 圖片拖動(dòng)時(shí),記錄圖片當(dāng)前位置,并實(shí)時(shí)計(jì)算圖片大小、旋轉(zhuǎn)角度等,并存儲(chǔ)至itemList中 -->
@touchmove="(e) => WraptouchMove(e, item)"
<!--一般不做處理 -->
@touchend="(e) => WraptouchEnd(e, item)"
mode="widthFix"
>
</image>
<!-- 刪除按鈕 -->
<image
class='x'
src='/static/close.png'
:style="{transform: 'scale(' + item.oScale + ')', 'transform-origin': center}"
@click="(e) => deleteItem(e, item)"
>
</image>
<!-- 圖片放縮按鈕 -->
<image
v-if="item.image"
class='o'
src='/static/scale.png'
:style="{transform: 'scale(' + item.oScale + ')', 'transform-origin': center}"
<!-- 圖片點(diǎn)擊時(shí),記錄點(diǎn)擊圖片當(dāng)前坐標(biāo),半徑 -->
@touchstart="(e) => oTouchStart(e, item)"
<!-- 圖片點(diǎn)擊時(shí),記錄點(diǎn)擊圖片當(dāng)前坐標(biāo),計(jì)算新的半徑(得到scale縮放比例)計(jì)算角度差,獲取當(dāng)前角度 -->
@touchmove="(e) => oTouchMove(e, item)"
@touchend="(e) => WraptouchEnd(e, item)"
>
</image>
</view>
</view>
</block>
</view>
<canvas canvas-id="myCanvas" :style="
'position:absolute;border: 2px solid red; width:' +
imageW +
'px;height:' +
imageH +
'px;top:-9999px;left:-9999px;'
">
</canvas>
</view>
// 點(diǎn)擊圖片或文字
WraptouchStart(e, it) {
currentChoose = it
// 循環(huán)圖片數(shù)組獲取點(diǎn)擊的圖片信息
for (let i = 0; i < items.length; i++) {
items[i].active = false;
if (it.id == items[i].id) {
index = i;
items[index].active = true;
}
}
// this.setData({
// itemList: items
// })
this.setList(items, 'itemList')
// 獲取點(diǎn)擊的坐標(biāo)值 lx ly是圖片點(diǎn)擊時(shí)的位置值
items[index].lx = e.touches[0].clientX;
items[index].ly = e.touches[0].clientY;
},
// 拖動(dòng)圖片
WraptouchMove(e) {
// 獲取點(diǎn)擊的坐標(biāo)值 _lx _ly 是圖片移動(dòng)的位置值
items[index]._lx = e.touches[0].clientX;
items[index]._ly = e.touches[0].clientY;
// left 是_lx 減去 lx,_ly 減去 ly,也就是現(xiàn)在位置,減去原來(lái)的位置。
items[index].left += items[index]._lx - items[index].lx;
items[index].top += items[index]._ly - items[index].ly;
// 同理更新圖片中心坐標(biāo)點(diǎn),用于旋轉(zhuǎn)
items[index].x += items[index]._lx - items[index].lx;
items[index].y += items[index]._ly - items[index].ly;
// 停止了以后,把lx的值賦值為現(xiàn)在的位置
items[index].lx = e.touches[0].clientX;
items[index].ly = e.touches[0].clientY;
// this.setData({
// itemList: items
// })
this.setList(items, 'itemList')
},
// 放開(kāi)圖片
WraptouchEnd(e, it) {
touchNum ++
clearTimeout(timer)
timer = null
timer = setTimeout(this.timeSta, 250)
},
// 計(jì)算坐標(biāo)點(diǎn)到圓心的距離
getDistancs(cx, cy, pointer_x, pointer_y) {
var ox = pointer_x - cx;
var oy = pointer_y - cy;
return Math.sqrt(
ox * ox + oy * oy
);
},
/*
*參數(shù)cx和cy為圖片圓心坐標(biāo)
*參數(shù)pointer_x和pointer_y為手點(diǎn)擊的坐標(biāo)
*返回值為手點(diǎn)擊的坐標(biāo)到圓心的角度
*/
countDeg(cx, cy, pointer_x, pointer_y) {
var ox = pointer_x - cx;
var oy = pointer_y - cy;
var to = Math.abs(ox / oy); // 勾股定理,計(jì)算當(dāng)前點(diǎn)距離中心點(diǎn)的距離。
var angle = Math.atan(to) / (2 * Math.PI) * 360; // 計(jì)算當(dāng)前角度
if (ox < 0 && oy < 0) //相對(duì)在左上角,第四象限,js中坐標(biāo)系是從左上角開(kāi)始的,這里的象限是正常坐標(biāo)系
{
angle = -angle;
} else if (ox <= 0 && oy >= 0) //左下角,3象限
{
angle = -(180 - angle)
} else if (ox > 0 && oy < 0) //右上角,1象限
{
angle = angle;
} else if (ox > 0 && oy > 0) //右下角,2象限
{
angle = 180 - angle;
}
return angle; // 返回角度
},
體驗(yàn):文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-707312.html
到了這里,關(guān)于uni-app(微信小程序)圖片旋轉(zhuǎn)放縮,文字繪制、海報(bào)繪制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!