当前位置: 首页 > news >正文

网站实名认证要钱吗wordpress图片网盘插件腾讯

网站实名认证要钱吗,wordpress图片网盘插件腾讯,中小企业网络设计论文,网络推广官网首页嗯,手撸官方文档2天#xff0c;发现没啥用#xff0c;尤其是动画,那种计算出来的#xff0c;根本想不到。因此学着学了抱着要做个东西的想法,去网上找相关案例,最终做出了这个裁剪工具。 PS :先说一下思路: 核心实现有3个canvas图层, 其中一个负责图片的预览。另外2个叠加到…嗯,手撸官方文档2天发现没啥用尤其是动画,那种计算出来的根本想不到。因此学着学了抱着要做个东西的想法,去网上找相关案例,最终做出了这个裁剪工具。 PS :先说一下思路: 核心实现有3个canvas图层, 其中一个负责图片的预览。另外2个叠加到一起,底层canvas负责图片的渲染; 上层的canvas负责蒙版的绘制,和选择框(挖空)区域的绘制。我们将,移动选择框,记录的坐标和宽高,一个是同步到蒙版canvas里面,实现挖空。第二个同步到图片渲染canvas,通过getImageData()方法,拿取选择框挖空的区域的像素数据,渲染到图片预览canvas里面,然后通过canvas的toBlob()方法将预览canvas,导出成blobUrl,实现图片下载。 针对部分核心功能进行思路讲解。 1.上传图片 FileReader.readAsDataURL() - Web API 接口参考 | MDN (mozilla.org) 在 web 应用程序中使用文件 - Web API 接口参考 | MDN (mozilla.org) 下面,我们点击upBut,从而触发upInp的change事件,从而触发文件上传。我们对文件上传的类型进行是不是图片判断。然后,将图片File ,通过FileReader对象的readAsDataURL(File)方法,将图片File转换为dataUrl,并封装成Img对象。进而绘制到图片渲染canvas里面。 除此以外涉及到的函数,下文都会讲到。 input typefile idup-inp name文件上传 styledisplay: none /button typebutton idup-but上传/buttonlet upBut document.getElementById(up-but)let upInp document.getElementById(up-inp) upBut.addEventListener(click, (e) { // 给按钮绑定事件,点击 input typefile,从而弹出文件上传框upInp.click()})// 上传图片const updateFile (e) {let file e.target.files[0]if (!file.type.startsWith(image)) {alert(只允许上传图片)return}const reader new FileReader()reader.onload (e) { // 利用fileReader将file文件转换成dataUrllet img1 new Image() // 转换成img对象,进而绘画到canvas里面img1.src e.target.resultimg img1img1.onload (e) { // 读取完毕之后selectCropObj computeImage({imgWidth: img.width,imgHeight: img.height,width: cropCardbg.width,height: cropCardbg.height,})initImgObj JSON.parse(JSON.stringify(selectCropObj))drawImage(initImgObj)drawModal()drawClip()drawClipDiv()imgPreview()cropModal.style.display noneclip.style.display block}}reader.readAsDataURL(file)}upInp.addEventListener(change, updateFile) 2. 蒙版绘制 蒙版说白了就是占据canvas画布全部的半透明矩形。 // 画模版const drawModal () {ctxCardbg.clearRect(0, 0, cropCardbg.width, cropCardbg.height)ctxCardbg.fillStyle rgba(0,0,0,0.5)ctxCardbg.fillRect(0, 0, cropCardbg.width, cropCardbg.height)} 3.挖空 挖空:蒙版随选择框的移动要扣除的透明区域。 我们先绘制蒙版然后用clearRect()方法清除指定区域( 随着选择框移动,对应的在蒙版canvas里面的坐标和宽高围绕的区域,清除这个区域),达到挖空的效果。 // 挖空const drawClip () {ctxCardbg.clearRect(selectCropObj.x, selectCropObj.y, selectCropObj.w, selectCropObj.h)} 4.选择框的绘制 我们先封装一个函数,用来注册拖拽选择框(中心和8个点)的鼠标按下、移动、抬起事件。 // 注册选择框拖拽事件const registerEvents () {// 注册那8个拖拽点事件const register (_class) {let node document.querySelector(.${_class})node.addEventListener(mousedown, (e) {down true})node.addEventListener(mousemove, carMouseMove)node.addEventListener(mouseup, function (e) {down false})}register(top-center)register(bottom-center)register(left-center)register(right-center)register(bottom-right)register(bottom-left)register(top-right)register(top-left)// 注册拖拽中央移动的事件let clip document.getElementById(crop-clip)clip.addEventListener(mousedown, (e) {down true})clip.addEventListener(mousemove, carMouseMove)clip.addEventListener(mouseup, (e) {down false})} 这是拖拽选择框的html 结构。我们的选择框采用html绘制,由于它和另外2个叠加的canvas,由于父元素相对定位,子绝对定位叠在一起,因此选择框的left和top值,就相当于canvas里面的x、y坐标,我们同样将选择框宽高映射到,canvas的挖空区域,从而在拖拽的时候实现实时挖空的效果。 div idcrop-clip styledisplay: nonediv classdot top-left/divdiv classdot top-right/divdiv classdot top-center/divdiv classdot bottom-left/divdiv classdot bottom-center/divdiv classdot bottom-right/divdiv classdot left-center/divdiv classdot right-center/div/div 下面通过selectCropObj对象,记录选择框在移动期间的x,y坐标,以及选择框变化的宽高。 // 在canvas的裁剪框尺寸和坐标let selectCropObj {x: 0,y: 0,w: 0,h: 0,} 这是我们处理选择框移动的函数。根据拖拽的元素(选择框中央、其余8个点)的携带的class不同,从而调用不同的移动处理方法。 // 通过拖拽事件,调用的方法(将选择框中央拖拽 ,和点拖拽通过一个函数处理)const carMouseMove (e) {// 两个都是false,证明我们一个没按下if (img null) {return}if (!down) {return}let ele e.targetlet { movementX, movementY } econst isExistsCls (_cls) {for (let i 0; i ele.classList.length; i) {const val ele.classList[i]if (val _cls) {return true}}return false}// 中央拖拽if (ele.id crop-clip) {selectCropObj.x movementXselectCropObj.y movementY// 点拖拽} else if (isExistsCls(top-left)) {// 坐标和宽高的都要变selectCropObj.x movementXselectCropObj.y movementYselectCropObj.w -movementXselectCropObj.h -movementY} else if (isExistsCls(top-right)) {selectCropObj.y movementYselectCropObj.w movementXselectCropObj.h -movementY} else if (isExistsCls(top-center)) {selectCropObj.y movementYselectCropObj.h -movementY} else if (isExistsCls(bottom-left)) {selectCropObj.x movementXselectCropObj.y movementYselectCropObj.w -movementXselectCropObj.h movementY} else if (isExistsCls(bottom-right)) {selectCropObj.w movementXselectCropObj.h movementY} else if (isExistsCls(bottom-center)) {selectCropObj.h movementY} else if (isExistsCls(left-center)) {selectCropObj.x movementXselectCropObj.w -movementX} else if (isExistsCls(right-center)) {selectCropObj.w movementX}drawClipDiv()drawModal()drawClip()imgPreview()} 对应选择框的具体绘制方法。 const drawClipDiv () {let cropClip document.getElementById(crop-clip)cropClip.style.width ${selectCropObj.w}pxcropClip.style.height ${selectCropObj.h}pxcropClip.style.left ${selectCropObj.x}pxcropClip.style.top ${selectCropObj.y}px} 5.画图像 就是清除之前渲染到图片canvas里面的图像,并将新的图片绘制到上面。 // 画图像const drawImage ({ x, y, w, h }) {ctxImg.clearRect(0, 0, cropImg.width, cropImg.height)ctxImg.drawImage(img, x, y, w, h)} 6.图片旋转 CanvasRenderingContext2D.rotate() - Web API 接口参考 | MDN (mozilla.org) 关于图片旋转这里,就是现将原点移动canvas画布中央(图像中央),然后定义旋转角度,然后又将原点移动回去,然后画的图像就是围绕中心旋转的。 主要是围绕图像的中心原点旋转。 大家可以自行去网上找关于rotate让图像围绕中心原点旋转的问题。因为作者也没能明白。 // 主要是这段代码:             ctxImg.translate(cropImg.width / 2, cropImg.height / 2)            ctxImg.rotate(angle)            ctxImg.translate(-cropImg.width / 2, -cropImg.height / 2) // 向右、左转(每次向左30度、向右30度)图片const imgRotate (e, t 1) {if (img null) {alert(请先上传图片)return}if (t 1) {// 向右转逆时针angle -30 * (Math.PI / 180)} else {// 向左转顺时针angle 30 * (Math.PI / 180)}ctxImg.clearRect(0, 0, cropImg.width, cropImg.height)ctxImg.translate(cropImg.width / 2, cropImg.height / 2)ctxImg.rotate(angle)ctxImg.translate(-cropImg.width / 2, -cropImg.height / 2)drawImage(initImgObj)imgPreview()} 7.图片扩大和缩小 通过initImgObj对象记录图像渲染到图片渲染canvas的尺寸和坐标。 // 图像渲染到到canvas的坐标尺寸和坐标let initImgObj {// 主要是为了缩放/扩大图片用x: 0,y: 0,w: 0,h: 0,} 通过computeImage()函数,计算出图像要在canvas画布中央实际渲染的坐标和尺寸。 // 计算图像在canvas实际渲染的图片坐标和宽高。(居于canvas中央,尺寸小于画布尺寸)const computeImage function ({ imgWidth, imgHeight, width, height, base 1 }) {if (imgWidth / base width imgHeight / base height) {return {x: (width - imgWidth) / 2,y: (height - imgHeight) / 2,w: imgWidth / base,h: imgHeight / base,}}return computeImage({imgWidth,imgHeight,width,height,base: base 0.1,})} 通过计算 initImgObj对象的放大、缩小后的宽高,然后通过computeImage()方法计算出canvas实际渲染的图像坐标和尺寸,并渲染。 // 缩小/扩大图片const imgScale (e, t) {if (img null) {alert(请先上传图片)return}let { w, h } initImgObjif (t 1) {// 缩小w w / 2h h / 2} else {// 扩大w w * 2h h * 2}// 重新求出缩小、放大之后的图片宽高和坐标。initImgObj computeImage({imgWidth: w,imgHeight: h,width: cropImg.width,height: cropImg.height,})drawImage(initImgObj)imgPreview()} 8.图片预览 ImageData - Web API 接口参考 | MDN (mozilla.org) 通过选择框拖拽,记录的 selectCropObj对象的坐标和宽高信息。 通过getImageData()方法获取图片渲染canvas里面的ImageData对象,并通过putImageData()方法将这个对象渲染到图片预览canvas里面。 // 图片预览const imgPreview () {ctxPreview.clearRect(0, 0, cropPreview.width, cropPreview.height)let { x, y, w, h } selectCropObjlet imgData ctxImg.getImageData(x, y, w, h)ctxPreview.putImageData(imgData, x, y)} 9.保存预览图片 HTMLCanvasElement.toBlob() - Web API 接口参考 | MDN (mozilla.org) HTMLCanvasElement.toDataURL() - Web API 接口参考 | MDN (mozilla.org) 我们通过,canvas的toBlob()方法将canvas画布转换为blobUrl,然后就是创建一个a 元素,并将这个url封装成a的href属性,用日期作为下载的图片名字用js模拟点击实现下载。 // 保存裁剪图片const saveImg (e) {if (img null) {alert(请先上传图片)return}cropPreview.toBlob((blob) {// 下载图片let a document.createElement(a)a.href window.URL.createObjectURL(blob)a.download ${getDateStr(new Date())}.png a.dispatchEvent(new MouseEvent(click))})} 完整代码 !DOCTYPE html html langenheadmeta charsetUTF-8 /meta nameviewport contentwidthdevice-width, initial-scale1.0 /title图片裁剪工具/titlestyle* {padding: 0;margin: 0;}#crop-tool {position: relative;overflow: hidden;width: 500px;height: 300px;margin: 100px auto;border: 1px solid black;border-radius: 15px;}#crop-img {z-index: -1;top: 0;left: 0;background: url(./img/mosaic.jpg);}#crop-cardbg {position: absolute;top: 0;left: 0;}#crop-modal {position: absolute;top: 0;left: 0;}#crop-clip {position: absolute;left: 25px;top: 37.1364px;cursor: all-scroll;width: 308.091px;height: 197.864px;border: 1px solid rgb(30, 158, 251);}#crop-modal {position: absolute;left: 0;top: 0;width: 500px;height: 300px;line-height: 300px;font-size: 30px;font-weight: 700;text-align: center;color: white;background-color: rgba(0, 0, 0, 0.5);}#crop-preview {border: 1px solid black;border-radius: 15px;width: 500px;height: 300px;margin: 0 700px;}#crop-but {width: 400px;margin: 0 auto;}button {width: 50px;}#crop-clip .dot {position: absolute;width: 20px;height: 20px;border-radius: 50%;background: #1e9efb;}#crop-clip .top-left {top: -10px;left: -10px;cursor: nwse-resize;}#crop-clip .top-right {top: -10px;right: -10px;cursor: nesw-resize;}#crop-clip .top-center {top: -10px;left: 50%;transform: translate(-50%);cursor: ns-resize;}#crop-clip .bottom-left {bottom: -10px;left: -10px;cursor: nesw-resize;}#crop-clip .bottom-center {bottom: -10px;left: 50%;transform: translate(-50%);cursor: ns-resize;}#crop-clip .bottom-right {bottom: -10px;right: -10px;cursor: nwse-resize;}#crop-clip .left-center {top: 50%;transform: translateY(-50%);left: -10px;cursor: ew-resize;}#crop-clip .right-center {top: 50%;transform: translateY(-50%);right: -10px;cursor: ew-resize;}/style!-- link relstylesheet href./css/iconfont.css / --/headbodydiv idcrop-toolcanvas idcrop-img width500 height300/canvascanvas idcrop-cardbg width500 height300/canvasdiv idcrop-clip styledisplay: nonediv classdot top-left/divdiv classdot top-right/divdiv classdot top-center/divdiv classdot bottom-left/divdiv classdot bottom-center/divdiv classdot bottom-right/divdiv classdot left-center/divdiv classdot right-center/div/divdiv idcrop-modal请先上传图片/div/divcanvas idcrop-preview width500 height300 /canvasdiv idcrop-butinput typefile idup-inp name文件上传 styledisplay: none /button typebutton idup-but上传/buttonbutton typebutton idadd-but/buttonbutton typebutton iddel-but-/buttonbutton typebutton idxzz-butleft!-- span classiconfont icon-xiangzuoxuanzhuan/span --/buttonbutton typebutton idxyz-butright!-- span classiconfont icon-xiangyouxuanzhuan/span --/buttonbutton typebutton idsave-but截图/button/div/bodyscript src./js/Index.js/scriptscript///variable///// 按钮组let upBut document.getElementById(up-but)let saveBut document.getElementById(save-but)let addBut document.getElementById(add-but)let delBut document.getElementById(del-but)let xzzBut document.getElementById(xzz-but)let xyzBut document.getElementById(xyz-but)let upInp document.getElementById(up-inp)let cropImg document.querySelector(#crop-img) // 背景层let cropCardbg document.querySelector(#crop-cardbg) // 裁剪层let cropPreview document.querySelector(#crop-preview) // 裁剪层let cropModal document.querySelector(#crop-modal) // 遮罩层let clip document.getElementById(crop-clip) // 选择框let ctxCardbg cropCardbg.getContext(2d)let ctxImg cropImg.getContext(2d)let ctxPreview cropPreview.getContext(2d)// 在canvas的裁剪框尺寸和坐标let selectCropObj {x: 0,y: 0,w: 0,h: 0,}// 一开始存储到canvas的坐标尺寸和坐标let initImgObj {// 主要是为了缩放/扩大图片用x: 0,y: 0,w: 0,h: 0,}let img nulllet down false // 中心拖拽或者按钮拖拽let angle 0 // 旋转角度///method///upBut.addEventListener(click, (e) {upInp.click()})// 上传图片const updateFile function (e) {let file e.target.files[0]if (!file.type.startsWith(image)) {alert(只允许上传图片)return}const reader new FileReader()reader.onload (e) {let img1 new Image()img1.src e.target.resultimg img1img1.onload (e) {// 读取完毕之后selectCropObj computeImage({imgWidth: img.width,imgHeight: img.height,width: cropCardbg.width,height: cropCardbg.height,})initImgObj JSON.parse(JSON.stringify(selectCropObj))drawImage(initImgObj)drawModal()drawClip()drawClipDiv()imgPreview()cropModal.style.display noneclip.style.display block}}reader.readAsDataURL(file)}upInp.addEventListener(change, updateFile)// 保存裁剪图片const saveImg (e) {if (img null) {alert(请先上传图片)return}cropPreview.toBlob((blob) {let a document.createElement(a)a.href window.URL.createObjectURL(blob)a.download ${getDateStr(new Date())}.pnga.dispatchEvent(new MouseEvent(click))})}saveBut.addEventListener(click, saveImg)// 图片预览const imgPreview () {ctxPreview.clearRect(0, 0, cropPreview.width, cropPreview.height)let { x, y, w, h } selectCropObjlet imgData ctxImg.getImageData(x, y, w, h)ctxPreview.putImageData(imgData, x, y)}// 缩小/扩大图片const imgScale (e, t) {if (img null) {alert(请先上传图片)return}let { w, h } initImgObjif (t 1) {// 缩小w w / 2h h / 2} else {// 扩大w w * 2h h * 2}// 重新求出缩小方法的图片坐标initImgObj computeImage({imgWidth: w,imgHeight: h,width: cropImg.width,height: cropImg.height,})drawImage(initImgObj)imgPreview()}// 向右、左转(每次向左90度、向右90度)图片const imgRotate (e, t 1) {if (img null) {alert(请先上传图片)return}if (t 1) {// 向右转逆时针angle -30 * (Math.PI / 180)} else {// 向左转顺时针angle 30 * (Math.PI / 180)}ctxImg.clearRect(0, 0, cropImg.width, cropImg.height)ctxImg.translate(cropImg.width / 2, cropImg.height / 2)ctxImg.rotate(angle)ctxImg.translate(-cropImg.width / 2, -cropImg.height / 2)drawImage(initImgObj)imgPreview()}delBut.addEventListener(click, (e) {imgScale(e, 1)})addBut.addEventListener(click, (e) {imgScale(e, 2)})xzzBut.addEventListener(click, (e) {imgRotate(e, 1)})xyzBut.addEventListener(click, (e) {imgRotate(e, 2)})// 画模版const drawModal function () {ctxCardbg.clearRect(0, 0, cropCardbg.width, cropCardbg.height)ctxCardbg.fillStyle rgba(0,0,0,0.5)ctxCardbg.fillRect(0, 0, cropCardbg.width, cropCardbg.height)}// 计算图片在canvas实际坐标和尺寸const computeImage function ({ imgWidth, imgHeight, width, height, base 1 }) {if (imgWidth / base width imgHeight / base height) {return {x: (width - imgWidth) / 2,y: (height - imgHeight) / 2,w: imgWidth / base,h: imgHeight / base,}}return computeImage({imgWidth,imgHeight,width,height,base: base 0.1,})}// 画图像const drawImage function ({ x, y, w, h }) {ctxImg.clearRect(0, 0, cropImg.width, cropImg.height)ctxImg.drawImage(img, x, y, w, h)}// 挖空const drawClip function () {ctxCardbg.save()ctxCardbg.clearRect(selectCropObj.x, selectCropObj.y, selectCropObj.w, selectCropObj.h)ctxCardbg.restore()}// 挖空时,选择框的变化const drawClipDiv () {let cropClip document.getElementById(crop-clip)cropClip.style.width ${selectCropObj.w}pxcropClip.style.height ${selectCropObj.h}pxcropClip.style.left ${selectCropObj.x}pxcropClip.style.top ${selectCropObj.y}px}// 卡片拖拽事件,调用的方法(将选择框中央拖拽 ,和点拖拽一个方法处理)const carMouseMove (e) {// 两个都是false,证明我们一个没按下if (img null) {return}if (!down) {return}let ele e.targetlet { movementX, movementY } econst isExistsCls (_cls) {for (let i 0; i ele.classList.length; i) {const val ele.classList[i]if (val _cls) {return true}}return false}// 中央拖拽if (ele.id crop-clip) {selectCropObj.x movementXselectCropObj.y movementY// 点拖拽} else if (isExistsCls(top-left)) {// 坐标和宽高的都要变selectCropObj.x movementXselectCropObj.y movementYselectCropObj.w -movementXselectCropObj.h -movementY} else if (isExistsCls(top-right)) {selectCropObj.y movementYselectCropObj.w movementXselectCropObj.h -movementY} else if (isExistsCls(top-center)) {selectCropObj.y movementYselectCropObj.h -movementY} else if (isExistsCls(bottom-left)) {selectCropObj.x movementXselectCropObj.y movementYselectCropObj.w -movementXselectCropObj.h movementY} else if (isExistsCls(bottom-right)) {selectCropObj.w movementXselectCropObj.h movementY} else if (isExistsCls(bottom-center)) {selectCropObj.h movementY} else if (isExistsCls(left-center)) {selectCropObj.x movementXselectCropObj.w -movementX} else if (isExistsCls(right-center)) {selectCropObj.w movementX}drawClipDiv()drawModal()drawClip()imgPreview()}// 注册选择框拖拽事件const registerEvents () {// 注册那8个拖拽点事件const register (_class) {let node document.querySelector(.${_class})node.addEventListener(mousedown, (e) {down true})node.addEventListener(mousemove, carMouseMove)node.addEventListener(mouseup, function (e) {down false})}register(top-center)register(bottom-center)register(left-center)register(right-center)register(bottom-right)register(bottom-left)register(top-right)register(top-left)// 注册拖拽中央移动的事件let clip document.getElementById(crop-clip)clip.addEventListener(mousedown, (e) {down true})clip.addEventListener(mousemove, carMouseMove)clip.addEventListener(mouseup, (e) {down false})}registerEvents()/script /htmlconst getDateStr (time, tag1 -, tag2 :) {const date new Date(time)let y date.getFullYear()let M date.getMonth() 1let d date.getDate()let h date.getHours()let m date.getMinutes()let s date.getSeconds()return ${y}${tag1}${M}${tag1}${d} ${h}${tag2}${m}${tag2}${s} }
http://www.zqtcl.cn/news/34663/

相关文章:

  • 郑州免费自助建站模板怎么用dw做博客网站
  • 网站建设有几块商品网站建设实训报告
  • 专业制作彩铃网站做网站的维护成本
  • 品牌网站建设服务机构帝国做双语网站
  • 怎么黑进网站后台尚海整装
  • 网站建设英文如何表达河北石家庄建设信息网
  • 傻瓜网站建设软件做网站如何分类产品
  • wordpress最大的网站旅游网站开发工具
  • 宝山做网站公司霞浦县网站seo优化排名
  • 查网站备案信息长沙市网站推广公司
  • 购物网站哪个最便宜网站建设咨询推荐
  • 网站开发公司多少钱免费搭建贴吧系统网站
  • 正规的企业网站建设邮箱格式怎么写
  • 常用网站设计缩略图wordpress 手机版主题
  • 建设完网站成功后需要注意什么图片制作视频
  • 大学生做推送的网站高校教学网站建设
  • 中国建设银行官方网站e路航下载dw建设网站的代码模板下载
  • 工艺品网站怎么做网站网页能自己做吗
  • 网站建设分类网站建设优化服务特色
  • 怎样建设一个自己的网站首页微信wordpress插件
  • 企业网站推广阶段wordpress关闭手机访问不了
  • 数码网站模板模板大全免费
  • 大亨网站开发网站设计制作一般多少钱
  • 网站备案完电信怎么制作自己公司网站
  • 泰安建设信息网站h5制作模板官网
  • 做网站需要懂什么软件wordpress 礼物说模板
  • 网站建站系统中国万维网官网域名注册网站
  • 网站绝对地址制作网站需要哪些工作
  • 淘宝客自建网站黔西南州网站建设
  • 云网站 深圳滨州网站seo