需求:图片比例自适应屏幕,放大缩小,马赛克,画笔粗细可调整;

具体实现如下图:

图中可看出马赛克画笔粗细的不同,打码的大小也不同, 第四个按钮是全图重置,点击橡皮按住A/t键和鼠标左键可局部擦除已打码的部分。

我们项目用的是若依ruoyi的框架,vue+elementUI,所以代码中含有一些框架自带的API,若和你的项目不同,可以忽略,只看js或者vue部分。

话不多说上代码:

先是页面的一些基础功能,图片比例自适应屏幕,放大缩小,图片保存等。

<template><div class="app-container image_mosaic" v-loading="loading"><el-card class="box-card"><div slot="header" class="clearfix"><el-popoverplacement="bottom"style="margin-right:10px;"trigger="hover"><div><div @click="selectType(1)" class="mosaic_type"><div class="pen_type" style="height:2px;"></div></div><div @click="selectType(2)" class="mosaic_type"><div class="pen_type" style="height:4px;"></div></div><div @click="selectType(3)" class="mosaic_type"><div class="pen_type" style="height:6px;"></div></div><div @click="selectType(4)" class="mosaic_type"><div class="pen_type" style="height:8px;"></div></div></div><el-button el-button slot="reference" @click="visible = !visible" title="马赛克"  type="primary" :plain="isEditImg" id="drawSwitch"><img class="btn_icons" src="@/assets/icons/edit.png"/></el-button></el-popover><el-button title="橡皮擦" type="primary" :plain="isClearImg" id='clearSwitch'><img class="btn_icons" src="@/assets/icons/eraser.png"/></el-button><el-button title="全图马赛克" type="primary" id='drawAll'><img class="btn_icons" src="@/assets/icons/mosaicFull.png"/></el-button><el-button title="重置" type="primary" id='clearAll'><img class="btn_icons" src="@/assets/icons/back.png"/></el-button><el-button title="下载" type="primary" @click="download"><img class="btn_icons" src="@/assets/icons/download.png"/></el-button><el-button title="1:1" v-if="nowRate==100" type="primary" id='resizeImg' @click="resizeImg" ><img class="btn_icons" src="@/assets/icons/resize-01.png"/></el-button><el-button title="1:1" v-else type="primary" id='resizeImg' @click="resizeImg" ><img class="btn_icons" src="@/assets/icons/resize-02.png"/></el-button><el-button title="放大" type="primary" id='zoomIn' @click="zoomIn" ><img class="btn_icons" src="@/assets/icons/zoomIn.png"/></el-button><el-button title="缩小" type="primary" id='zoomOut' @click="zoomOut"><img class="btn_icons" src="@/assets/icons/zoomOut.png"/></el-button><el-button title="保存" :disabled="isSave" style="float: right;display: flex;align-items: center;" type="primary" @click="dialogUpload" ><img class="btn_icons" style="margin-top:-3px" src="@/assets/icons/save.png"/> 保存</el-button></div><div class="out_box"><div id="canvasBox"><canvas id="canvas" v-drag="{isEditImg,isClearImg}" class="drag_box"></canvas></div><div v-show="showNowRate" class="rate_box">{{nowRate}}%</div></div></el-card></div>
</template><script>
import Mosaic from './mosaic'
import{ fileExport } from "@/api/project/newProject";
import { updateFeedback } from "@/api/inforDelivery/questionManage.js";let globalMosaic = {}
let MouseEvents = {}export default {name: 'editPhoto',data(){return{visible: false,showAlert: false,loading: false,isEditImg: false,isClearImg: false,isSave: false,id:'',url:'',penNum:2,queriesId:'',feedback:'',flagId:'',fileUrl:'',sort:0,sizeRate: 0.1,imgUrl:'',nowRate:100,showNowRate: false,timer:'',that:this,hasRefresh:false}},directives:{drag:{update:function(el,binding){let dragBox = elif(binding.value.isEditImg || binding.value.isClearImg){dragBox.onmousedown = nulldragBox.style.cursor = 'default'}else{dragBox.style.cursor = 'move'dragBox.onmousedown = (e)=>{let boxX = e.clientX - dragBox.offsetLeftlet boxY = e.clientY - dragBox.offsetTopdocument.onmousemove = (e) =>{let left = e.clientX - boxXlet top = e.clientY - boxYdragBox.style.left = `${left}px`dragBox.style.top = `${top}px`}document.onmouseup = (e) =>{document.onmousemove = nulldocument.onmouseup = null}}}}}},activated(){if(!this.$store.state.questionPreview.isEditPhoto){this.init()this.$store.commit('SET_IS_EDIT_PHOTO', true)}},deactivated(){var tempImg = document.getElementById('canvas').toDataURL('image/jpeg')this.$store.commit('SET_EDIT_FORMDATA_URL', tempImg)},computed:{savePhoto(){return this.$store.state.questionPreview.savePhoto},visitedViews() {return this.$store.state.tagsView.visitedViews},},watch:{savePhoto:function(newVal,oldVal){if(newVal==true){this.loading = truevar tempImg = document.getElementById('canvas').toDataURL('image/jpeg')let file = this.base64ImgtoFile(tempImg,'测试图片名称')// 得到File对象let formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加this.feedback = this.$route.query.feedbackif(Array.isArray(this.feedback)){this.feedback = this.feedback.map(item=>{return item}).join("|");}else{this.feedback = this.feedback}this.queriesId = this.$route.query.queriesIdthis.flagId = this.$route.query.flagIdthis.fileUrl = this.$route.query.fileUrlthis.sort = this.$route.query.sort||''formData.append('file', file) //添加文件对象formData.append('queriesId', this.queriesId) //添加文件对象formData.append('feedback', this.feedback) //添加文件对象formData.append('flagId', this.flagId) //添加文件对象formData.append('fileUrl', this.fileUrl) //添加文件对象formData.append('sort', this.sort) //添加文件对象this.isSave = trueupdateFeedback(formData).then(res=>{this.loading = falsethis.isSave = falseif(res.responseCode==0){this.$message.success(res.responseMsg || '修改成功')let url = res.responseBody.fileUrllet feedback = res.responseBody.fileUrlList.join('|')this.$store.dispatch("tagsView/delView", this.$route);this.$router.push({path:`/inforDelivery/imagePreview/${this.id}`,query:{url,queriesId:this.queriesId,feedback,flagId:this.flagId,fileUrl:this.feedback}});setTimeout(()=>{this.$tab.refreshPage();},500)this.$store.commit('SET_SAVE_PHOTO', false)}else{this.$message.error('修改失败')}}).catch(res=>{this.loading = falsethis.isSave = falsethis.$message.error('修改失败')})}}},methods:{init(){globalMosaic = nullMouseEvents = nullthis.$store.commit('SET_EDIT_FORMDATA', "")this.$store.commit('SET_EDIT_FORMDATA_URL', {})this.showAlert= falsethis.loading= falsethis.isEditImg= falsethis.isClearImg= falsethis.isSave= falsethis.showNowRate= falsethis.nowRate = 100this.timer = ''this.id = this.$route.query.idthis.url = this.$route.query.urlthis.queriesId = this.$route.query.queriesIdthis.feedback = this.$route.query.feedbackif(Array.isArray(this.feedback)){this.feedback = this.feedback.map(item=>{return item}).join("|");}else{this.feedback = this.feedback}this.flagId = this.$route.query.flagIdthis.fileUrl = this.$route.query.fileUrlthis.sort = this.$route.query.sort||''let editFormData = {id:this.id,queriesId:this.queriesId,feedback:this.feedback,flagId:this.flagId,fileUrl:this.fileUrl,sort:this.sort ||'',}this.$store.commit('SET_EDIT_FORMDATA', editFormData)this.$store.commit('SET_IS_EDIT_PHOTO', false)this.getFiles(this.url)},selectType(e){  //选择画笔类型this.penNum = e*2let nowPenDiv = document.getElementsByClassName('mosaic_type')let nowPen = document.getElementsByClassName('pen_type')console.log(nowPenDiv[e-1].style,'nowPenDiv[e-1]');nowPenDiv.forEach((item,index)=>{item.style.backgroundColor = '#fff'item.onmouseover = function(){item.style.border='1px dashed #1890ff'}item.onmouseleave = function(){item.style.border='none'}})nowPen.forEach((item,index)=>{nowPenDiv[e-1].style.backgroundColor = '#1890ff'nowPen[e-1].style.backgroundColor = '#fff'},zoomIn(){  //图片放大let that = thisif(this.sizeRate<2){clearTimeout(this.timer)let canvas = document.getElementById('canvasBox')this.sizeRate += .1this.nowRate += 10this.showNowRate = truecanvas.style.transform=`scale(${this.sizeRate})`this.timer = setTimeout(()=>{that.showNowRate = false},1500)}else{this.showNowRate = trueclearTimeout(that.timer)that.timer = setTimeout(()=>{that.showNowRate = false},1500)return}},zoomOut(){  //图片缩小let that = thisclearTimeout(that.timer)if(this.sizeRate-.1>0.3){this.sizeRate -= .1this.nowRate -= 10this.showNowRate = truelet canvas = document.getElementById('canvasBox')canvas.style.transform=`scale(${this.sizeRate})`this.timer = setTimeout(()=>{that.showNowRate = false},1500)}else{this.showNowRate = truethis.timer = setTimeout(()=>{that.showNowRate = false},1500)return}},resizeImg(){let canvasBox = document.getElementById('canvasBox')let canvas = document.getElementById('canvas')canvasBox.style.transform='scale(1)'this.sizeRate = 1this.nowRate = 100canvas.style.left = ''canvas.style.top = ''},initImage(){ //初始化图片大小————1:1自适应屏幕let out_box = document.getElementsByClassName('out_box')let box_width = out_box[0].offsetWidthlet box_height = out_box[0].offsetHeightthis.nowRate = 100this.showNowRate = truethis.initMosaic(this.imgUrl, box_width, box_height)},drawImageToCanvas(url, width, height) { //canvas画图片let that = thislet canvas = document.getElementById('canvas')let ctx = canvas.getContext('2d')let rate = 0return new Promise((resolve, reject) => {const image = new Image()image.crossOrigin = 'Annoymous'image.src = ''image.onload = function () {if(image.width<image.height){  //若图片 高 大于 宽  H>Wcanvas.width = widthrate = width/image.widthcanvas.height = image.height*rateif(canvas.height>height){canvas.height = heightrate = height/image.heightcanvas.width = image.width*rate}}else {canvas.height = heightrate = height/image.heightcanvas.width = image.width*rateif(canvas.width>width){canvas.width = widthrate = width/image.widthcanvas.height = image.height*rate}}if(image.width<=width && image.height<=height){rate = 1}canvas.width = image.widthcanvas.height = image.heightctx.drawImage( this, 0, 0, canvas.width, canvas.height)canvas.style.transform=`scale(${rate})`that.sizeRate = 1that.loading = falsethat.timer = setTimeout(()=>{that.showNowRate = false},1500)resolve(ctx)ctx = nullcanvas = nullthat.resizeImg()}image.src = url})},initMosaic (url, width, height) {  //初始化马赛克let that = thisthis.drawImageToCanvas(url, width, height).then(ctx => {this.isEditImg = falsethis.isClearImg = falseglobalMosaic = new Mosaic(ctx, {tileWidth: 10*this.penNum,  //此处考虑到马赛克一般由四个正方形组成,所以宽高都一致,且动态获取画笔粗细 this.penNumbrushSize: 2,})MouseEvents = {init () {globalMosaic.context.canvas.addEventListener('mousedown', MouseEvents.mousedown)},mousedown () {globalMosaic.context.canvas.addEventListener('mousemove', MouseEvents.mousemove)document.addEventListener('mouseup', MouseEvents.mouseup)},mousemove (e) {let X = e.offsetXlet Y = e.offsetYif (that.isClearImg) {globalMosaic.eraseTileByPoint(X, Y,parseInt(10*that.penNum),2)}if(that.isEditImg){that.$store.commit('SET_IS_EDIT_PHOTO', true)globalMosaic.drawTileByPoint(X, Y,parseInt(10*that.penNum),2)}},mouseup () {globalMosaic.context.canvas.removeEventListener('mousemove', MouseEvents.mousemove)document.removeEventListener('mouseup', MouseEvents.mouseup)},close () {globalMosaic.context.canvas.removeEventListener('mousedown', MouseEvents.mousedown)globalMosaic.context.canvas.removeEventListener('mousemove', MouseEvents.mousemove)}}MouseEvents.init()document.querySelector('#drawSwitch').addEventListener('click', () => {  //点击编辑按钮this.$nextTick(()=>{this.isEditImg = !this.isEditImgthis.isClearImg = false})console.log(this.isEditImg,'this.isEditImg');if(!this.isEditImg){MouseEvents.init()}else{MouseEvents.close()}})document.querySelector('#clearSwitch').addEventListener('click', () => {  //点击编辑按钮 this.$nextTick(()=>{this.isClearImg = !this.isClearImgthis.isEditImg = false})if(!this.isClearImg){MouseEvents.init()}else{MouseEvents.close()}})document.querySelector('#drawAll').addEventListener('click', () => {  //点击全图打码按钮this.$store.commit('SET_IS_EDIT_PHOTO', true)this.isEditImg = falsethis.isClearImg = falseglobalMosaic.drawAllTiles(parseInt(10*that.penNum))})document.querySelector('#clearAll').addEventListener('click', () => {  //点击重置图片按钮// this.$store.commit('SET_IS_EDIT_PHOTO', false)this.isEditImg = falsethis.isClearImg = falseglobalMosaic.eraseAllTiles(parseInt(10*that.penNum))})})},// 保存dialogUpload () {console.log(this.$route.query,'this.$route.query');this.loading = truevar tempImg = document.getElementById('canvas').toDataURL('image/jpeg')let file = this.base64ImgtoFile(tempImg,'测试图片名称')// 得到File对象let formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加let params = this.$store.state.questionPreview.editFormDatathis.feedback = params.feedbackthis.queriesId = params.queriesIdthis.flagId = params.flagIdthis.fileUrl = params.fileUrlthis.sort = params.sort||''this.id = params.idformData.append('file', file) //添加文件对象formData.append('queriesId', this.queriesId) //添加文件对象formData.append('feedback', this.feedback) //添加文件对象formData.append('flagId', this.flagId) //添加文件对象formData.append('fileUrl', this.fileUrl) //添加文件对象formData.append('sort', this.sort) //添加文件对象this.isSave = trueupdateFeedback(formData).then(res=>{this.loading = falsethis.isSave = falseif(res.responseCode==0){// console.log(res.responseBody);this.$message.success(res.responseMsg || '修改成功')let url = res.responseBody.fileUrllet feedback = res.responseBody.fileUrlList.join('|')// console.log(params);this.$store.dispatch("tagsView/delView", this.$route);this.$router.push({path:`/inforDelivery/imagePreview/${params.id}`,query:{url,queriesId:params.queriesId,feedback,flagId:params.flagId,fileUrl:params.feedback}});setTimeout(()=>{this.$tab.refreshPage();},500)this.$store.commit('SET_SAVE_PHOTO', false)}else{this.$message.error('修改失败')}}).catch(res=>{this.loading = falsethis.isSave = falsethis.$message.error('修改失败')})},// // 图片转base64base64ImgtoFile (dataurl, filename = 'file') {let arr = dataurl.split(',')const mime = arr[0].match(/:(.*?);/)[1]const suffix = mime.split('/')[1]const bstr = atob(arr[1])let n = bstr.lengtharr = nullconst u8arr = new Uint8Array(n)while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new File([u8arr], `${filename}.${suffix}`, {type: mime})},getFiles(fileUrl) {let params = {fileUrl}this.loading = truefileExport(params).then(res=>{this.loading = falselet imgUrl = window.URL.createObjectURL(new Blob([res],{type: "image/jpeg"}));res = nullthis.imgUrl = imgUrlthis.initImage()imgUrl = null}).catch(res=>{this.loading = false// this.$message.error('图片加载失败')})},download(){  //下载已打码的图片var tempImg = document.getElementById('canvas').toDataURL('image/jpeg')let file = this.base64ImgtoFile(tempImg, this.$route.query.url)// 得到File对象let formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加 formData.append('file', file) //添加文件对象let imgUrl = window.webkitURL.createObjectURL(file) || window.URL.createObjectURL(file) // imgUrl图片网络路径let a = document.createElement('a')a.href = imgUrla.target="_blank"a.download = this.$route.query.url// 下载文件的名字a.click()file = nulla.remove()}},beforeDestroy(){this.$store.commit('SET_IS_EDIT_PHOTO', false) //在vuex中修改是否已遍及过图片的判断,来展示组织弹出昂let canvas = document.getElementById('canvas')canvas.remove()globalMosaic = nullMouseEvents = null}
}
</script><style>
.out_box {height:75vh;overflow: hidden;
}
#canvasBox{width:90%;overflow-y: hidden;margin:0 auto;display: flex;justify-content: center;align-items: center;height: 75vh;overflow: hidden;
}
.btn_group{text-align:center;margin-top: 1%;
}
.btn_icons{display: inline-block;width: 18px;height: 18px;
}
.rate_box {position:absolute;right: 47.5%;top:50%;color: #fff;font-size: 20px;width: 120px;height: 40px;line-height: 40px;text-align: center;background-color: #5C5B5B;border-radius: 25px;
}
.drag_box {position: absolute;
}.mosaic_type {height: 30px;margin: 5px auto;display: flex;align-items: center;justify-content: center;
}
.pen_type{background-color: #46a6ff;width: 90px;
}
.mosaic_type:hover {border:1px dashed #1890ff;
}
.mosaic_type .el-radio-button__inner {border: none !important;border-radius: 3px !important;
}
</style>

下面是马赛克纯js内容,参考了一些大神们的代码,还有公司巨佬idea的支持,本来是用了git上的一个插件做马赛克这部分功能,但是由于插件不能满足调整画笔大小的功能,又在插件的基础上自行封装了;

/*** {*  context,*  imageData,*  width,*  height,*  tileWidth,*  tileHeight,*  tileRowSize,*  tileColumnSize,*  tiles: [{*      row,*      column,*      pixelWidth,*      pixelHeight,*      data,*      color,*      isFilled,*  }, ...]* }*/
class Mosaic {constructor(context, { tileWidth = 10, brushSize = 3 } = {}) {const { canvas } = context;this.context = context;this.brushSize = brushSize;this.width = canvas.width;this.height = canvas.height;this.tileWidth = tileWidth;// this.tileHeight = tileHeight;const { width, height } = this;this.imageData = context.getImageData(0, 0, width, height).data;this.tileRowSize = Math.ceil(height / this.tileWidth);this.tileColumnSize = Math.ceil(width / this.tileWidth);this.tiles = []; // All image tiles.// Set tiles.for (let i = 0; i < this.tileRowSize; i++) {for (let j = 0; j < this.tileColumnSize; j++) {const tile = {row: i,column: j,pixelWidth: this.tileWidth,// pixelHeight: tileHeight,pixelHeight: this.tileWidth,};if (j === this.column - 1) { // Last columntile.pixelWidth = width - (j * this.tileWidth);}if (i === this.row - 1) { // Last row// tile.pixelHeight = height - (i * tileHeight);tile.pixelHeight = height - (i * this.tileWidth);}// Set tile data;const data = [];// const pixelPosition = this.width * 4 * this.tileHeight * tile.row + tile.column * this.tileWidth * 4;const pixelPosition = this.width * 4 * this.tileWidth * tile.row + tile.column * this.tileWidth * 4;for (let i = 0, j = tile.pixelHeight; i < j; i++) {const position = pixelPosition + this.width * 4 * i;data.push.apply(data, this.imageData.slice(position, position + tile.pixelWidth * 4));};tile.data = data;this.tiles.push(tile);}}}drawTile(tiles,tileWidth) {tiles = [].concat(tiles);tiles.forEach((tile,index) => {if (tile.isFilled) {return false; // Already filled.}if (!tile.color) {let dataLen = tile.data.length;let r = 0, g = 0, b = 0, a = 0;for (let i = 0; i < dataLen; i += 4) {r += tile.data[i];g += tile.data[i + 1];b += tile.data[i + 2];a += tile.data[i + 3];}// Set tile color.let pixelLen = dataLen / 4;tile.color = {r: parseInt(r / pixelLen, 10),g: parseInt(g / pixelLen, 10),b: parseInt(b / pixelLen, 10),a: parseInt(a / pixelLen, 10),};}const color = tile.color;this.context.fillStyle=`rgba(${color.r}, ${color.g}, ${color.b}, ${color.a /255})`;let x,y;if(index==0 || index == 2){x = tile.column * this.tileWidth;}else{x = (tile.column * this.tileWidth) +(tileWidth-this.tileWidth);}if(index==2 || index == 3){y = (tile.row * this.tileWidth) +(tileWidth-this.tileWidth);}else{y = tile.row * this.tileWidth}const w = tileWidth;const h = tileWidth;console.log(x, y, w, h,'x, y, w, h',index,'index');this.context.clearRect(x, y, w, h); // Clear.this.context.fillRect(x, y, w, h); // Draw.tile.isFilled = true;});}drawTileByPoint(x, y, tileWidth, brushSize, isBrushSize = true) {const tile = this.getTilesByPoint(x, y, brushSize, isBrushSize);this.drawTile(tile,tileWidth);}getTilesByPoint(x, y, brushSize, isBrushSize = true) {const tiles = [];if (isBrushSize) {brushSize=brushSize||this.brushSize;let startRow = Math.max(0, Math.floor(y / this.tileWidth ) - Math.floor(brushSize / 2));let startColumn = Math.max(0, Math.floor(x / this.tileWidth ) - Math.floor(brushSize / 2));// let startRow = Math.max(0, Math.floor(y / this.tileHeight) - Math.floor(brushSize / 2));// let startColumn = Math.max(0, Math.floor(x / this.tileWidth) - Math.floor(brushSize / 2));let endRow = Math.min(this.tileRowSize, startRow + brushSize);let endColumn = Math.min(this.tileColumnSize, startColumn + brushSize);// Get tiles.while (startRow < endRow) {let column = startColumn;while (column < endColumn) {tiles.push(this.tiles[startRow * this.tileColumnSize + column]);column += 1;}startRow += 1;}}return tiles;}drawAllTiles(tileWidth) {this.drawTile(this.tiles,tileWidth);}eraseTile(tiles,tileWidth) {[].concat(tiles).forEach((tile) => {const x = tile.column *  this.tileWidth;const y = tile.row *  this.tileWidth;    const w = tile.pixelWidth;const h = tile.pixelHeight;var imgData = this.context.createImageData(w, h);tile.data.forEach((val, i) => {imgData.data[i] = val;})this.context.clearRect(x, y, w, h); // Clear.this.context.putImageData(imgData, x, y); // Draw.tile.isFilled = false;});}eraseTileByPoint(x, y, tileWidth, brushSize,isBrushSize = true) {const tile = this.getTilesByPoint(x, y, brushSize, isBrushSize);this.eraseTile(tile,tileWidth);}eraseAllTiles(tileWidth) {this.eraseTile(this.tiles,tileWidth);}
}export default Mosaic;

当然,代码中有很多不足的部分,欢迎大佬指出,小白退下啦。

前端图片放大缩小/比例自适应/打码/码大小可调整相关推荐

  1. Android实现图片放大缩小

    蓝蓝的天 蓝蓝的天,白云朵朵. White clouds in the blue sky. 目录视图 摘要视图 订阅 新版极客头条上线,每天一大波干货     任玉刚:Android开发者的职场规划  ...

  2. html如何控制图片自动放缩,如何用js控制图片放大缩小

    js控制图片放大缩小的效果,可以通过JavaScript的width和height属性来实现.其属性可以实现按比例放大和缩小图像尺寸的功能. 在前面的文章中,也为大家介绍了JS获取图片当前宽高和JS获 ...

  3. Android 图片放大缩小

    2019独角兽企业重金招聘Python工程师标准>>> 在android中,图片的放大和缩小是很重要的一个方法,我们主要用到的就是bitmap.MotionEvent .Matrix ...

  4. vue项目 一行js代码搞定点击图片放大缩小

    一行js代码搞定xue项目需要点击图片放大缩小,其实主要用的是用到了vue:class的动态切换,内容比较简单.一开始我把维护的需求想得太复杂了,和测试小姐姐聊了一下才反应过来. 两个月不到跟了四个项 ...

  5. iphone iPhone开发中如何将制作图片放大缩小代码实现案例

    1:原文摘自:http://mobile.51cto.com/iphone-285108.htm iPhone开发中如何将制作图片放大缩小案例是本文要介绍的内容,主要是来学习iphone开发中动画的制 ...

  6. 【Axure交互教程】滑块控制图片放大缩小效果

    作品名称:滑块控制图片放大缩小效果 作品编号:Case007 软件版本:Axure9 作品类型:交互案例 原型预览链接(附源文件下载链接):http://daisyaxure.com/demo/Cas ...

  7. js 图片放大缩小(动画效果)

    本文实现鼠标滑过图片事件,鼠标滑到图片上则图片逐渐放大,鼠标划走图片逐渐缩小到原大小.下面分析整个过程: 图片逐渐放大缩小怎么实现? 1.用css设置图片的宽和高的不同值可以实现大小不同的图片,那么通 ...

  8. css3 图片放大缩小闪烁效果

    直接把图片替换就可以了,我的图片是透明的,所以body设置为黑色的,不不要可以去掉 <!doctype html> <html lang="en"> < ...

  9. 图片放大缩小旋转左移右移镜像倒影android

    图片放大缩小旋转左移右移镜像倒影 demo: TestImage 1. 将 meinv.jpg 图片拷贝到以下目录TestImage\app\src\main\res\mipmap-hdpi 1.An ...

最新文章

  1. OD使用教程6 - 调试篇06|解密系列
  2. 如何看待程序媛们的职场焦虑和未来职业规划?
  3. cout、cerr、clog
  4. 固件升级校准_RS网络分析仪自检自校准方法-Agitekservice
  5. How CRM_JEST is influenced by status change in WebUI
  6. Linux之GDB命令(二)
  7. JDK 下载相关资料
  8. localstorage本地缓存
  9. 虚拟机续集:自动创建虚拟机virt-install、自动创建快照、kickstart自动安装虚拟机
  10. 杭州的马路上,突然多了6万张阿里人的笑脸
  11. Linux - Ubuntu下JDK配置
  12. python Flask 使用https 安全协议
  13. idea粘贴代码为什么都在一行_【学园】今天程序员的每一行代码都是未来高达身上的一颗螺丝...
  14. 学渣的心酸(求职篇)
  15. PS制作光束散射的旋转文字效果
  16. 突发奇想:用单片机开发一款最纯粹的智能水杯方案
  17. 吴伯凡-认知方法论-如何消除认知阑尾
  18. 电脑开机一直自动重启
  19. 激战2怎么选最新的服务器,选哪个服好?《激战2》高玩分析各服务器进驻人数...
  20. iWork8 U80GT 平板安装Ubuntu Desktop 20.04 64位教程(理论适用所有Linux64位发行版)

热门文章

  1. 茄子总结31/8/2022
  2. python爬虫需要哪些基础知识-【PYTHON】【爬虫】关于python爬虫的一些基础知识
  3. Ruoyi若依前后端分离框架【若依登录详细过程】
  4. 用c语言写个简单的电话薄
  5. [HTML5]简单网页本地音乐播放器
  6. 小日本的恶趣味?育碧让玩家用VR外设闻屁味
  7. 火狐浏览器插件开发小试
  8. Win11如何清除最近打开过的文件记录?
  9. 《你不懂我,我不怪你》 作者:余秋雨
  10. 华为鸿蒙系统怎么安装软件,华为鸿蒙系统2.0怎么进行安装?鸿蒙系统2.0安装步骤一览...