canvas实现图片马赛克的示例代码


Posted in HTML / CSS onMarch 26, 2018

1. 原生canvas实现用到的API

1) getContext(contextID) ---返回一个用于在画布上绘图的环境

复制代码
代码如下:

Canvas.getContext('2d') // 返回一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中

2)drawImage

drawImage(imgObj, x, y)  // 按原图大小绘制, x、y为图片在画布中的位置坐标
drawImage(imgObj, x, y, width, height) // 按指定宽高绘制
drawImage(imgObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight) // 从原来图片上某一个位置开始(sourceX,sourceY),指定长宽进行剪切(sourceWidth,sourceHeight),然后将剪切的内容放到位置为(destX,destY),宽度为(destWidth),高度为(destHeight)的位置上

canvas实现图片马赛克的示例代码

3) getImageData(x, y, width, height) ---获取矩形区域的图像信息

ctx.getImageData(0, 0, 10, 10) // 获取左上角坐标为(0, 0),宽高为区域内的图像信息
// 返回ImageData: { width: 10, height: 10, data: Uint8ClampedArray[400] }

4)beginPath() ---开始一条路径,或重置当前的路径 5)rect(x, y, width, height) ---绘制矩形

6)lineWidth ---设置或返回当前线条的宽度

7)fillStyle ---设置或返回用于填充绘画的颜色、渐变或模式

ctx.fillStyle = color|gradient|pattern

8)strokeStyle ---设置或返回用于笔触的颜色、渐变或模式

9)globalAlpha ---设置或返回绘图的当前透明值

10)fill() ---填充当前的图像(路径)。默认颜色是黑色

【注】如果路径未关闭,那么 fill() 方法会从路径结束点到开始点之间添加一条线,以关闭该路径,然后填充该路径。

11)stroke() ---会实际地绘制出通过 moveTo() 和 lineTo() 方法定义的路径。默认颜色是黑色

12)toDataURL(type, encoderOptions) ---导出图片,type为图片类型, encoderOptions图片质量,[0, 1]

Canvas.toDataURL("image/png", 1)

2. fabric.js

简化canvas编写的库,为canvas提供所缺少的对象模型

fabric.js能做的事

1)在canvas上创建、填充图形(包括图片、文字、规则图形和复杂路径组成图形)

2)给图形填充渐变颜色

3)组合图形(包括组合图形、图形文字、图片等)

4)设置图形动画集用户交互

5)生成JSON, SVG数据等

3.使用fabric.js实现用到的API

1)声明画布

let canvas =new fabric.Canvas('canvas') {
   width: 200,
   height: 200
}

插入图片

let imgInstance = new fabric.Image(imgElement,{
  left: 0,
  top: 0,
  width: 100,
  height: 100,
  angle: 0
}

3)设置背景图片 setBackgroundImage

canvas.setBackgroundImage(imgInstance)

4)renderAll() 重新绘制

5)on() 用户交互

canvas.on('mouse:down', function(options) {  
   console.log(options.e.clientX, options.e.clientY)  
})

// 监听事件
/* 
   mouse:down :鼠标按下时
   mouse:move :鼠标移动时
   mouse:up :鼠标抬起时
   after:render :画布重绘后
   object:selected:对象被选中
   object:moving:对象移动
   object:rotating:对象被旋转
   object:added:对象被加入
   object:removed对象被移除 
*/

6)getPointer()

7)setWidth()、setHeight() 设置canvas的宽高

8)画矩形

let rect = new fabric.Rect({
 left: 0,
 top: 0,
 width: 100,
 height: 100
})

add(obj) 添加图形

canvas.add(rect)

10)remove(obj) 移除图形

11)set() 设置对象内容

12)toDataURL(obj)

4.原生canvas实现代码

<template>
<div class="container">
  <div class="operations">
    <ul>
      <li @click="mosaic">马赛克</li>
      <li @click="addText">添加文字</li>
      <li @click="tailor">裁剪</li>
      <li @click="rotate">旋转</li>
      <li @click="exportImg">导出图片</li>
    </ul>
  </div>
  <canvas ref="imgContent" class="img-wrap">
    你的浏览器太low?
  </canvas>
</div>
</template>

<script>
  export default {
    data () {
      return {
        context: '',
        canvas: '',
        isMasic: false,
        isText: false,
        isTailor: false,
        isTranslate: false,
        squareEdgeLength: 20,
        angle: 0,
        img: ''
      }
    },
    mounted () {
      this.initData()
    },
    methods: {
      initData () {
        let imgContent = this.$refs.imgContent
        this.canvas = imgContent
        this.context = imgContent.getContext('2d')
        let  Img = new Image()
        this.image = Img
        Img.crossOrigin = "Anonymous"
        Img.src = 'http://oia85104s.bkt.clouddn.com/PictureUnlock_193139.pictureunlock.jpg'
        this.canvas.setAttribute('width', Img.width)
        this.canvas.setAttribute('height', Img.height)
        let self = this
        Img.onload = () => {
          let beginX, beginY, endX, endY
          self.context.drawImage(Img, 0, 0)
          self.context.save()

          self.canvas.addEventListener('mousedown', e => {
            beginX = e.offsetX
            beginY = e.offsetY
            self.canvas.addEventListener('mouseup', e => {
              endX = e.offsetX
              endY = e.offsetY
              if (self.isMasic) {
                self.makeGrid(beginX, beginY, endX - beginX, endY - beginY)
                return
              }
              if (self.isTailor) {
                self.context.drawImage(Img, beginX, beginY, endX - beginX, endY - beginY, 0, 0, endX - beginX, endY - beginY)
                return
              }
            })
          })
        }
      },
      drawRect  (x, y, width, height, fillStyle, lineWidth, strokeStyle, globalAlpha) {
        this.context.beginPath()
        this.context.rect(x, y, width, height)
        this.context.lineWidth = lineWidth
        this.context.strokeStyle = strokeStyle
        fillStyle && (this.context.fillStyle = fillStyle)
        globalAlpha && (this.context.globalAlpha = globalAlpha)

        this.context.fill()
        this.context.stroke()
      },
      // 打马赛克
      mosaic () {
        let self = this
        this.resetClickStatus()
        this.isMasic = true
      },
      makeGrid (beginX, beginY, rectWidth, rectHight) {
        const row = Math.round(rectWidth / this.squareEdgeLength) + 1
        const column = Math.round(rectHight / this.squareEdgeLength) + 1
        for (let i = 0; i < row * column; i++) {
          let x = (i % row) * this.squareEdgeLength + beginX
          let y = parseInt(i / row) * this.squareEdgeLength + beginY
          this.setColor(x, y)
        }
      },
      setColor (x, y) {
        const imgData = this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength).data
        let r = 0, g = 0, b = 0
        console.log(this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength), JSON.stringify(imgData))
        for (let i = 0; i < imgData.length; i += 4) {
          r += imgData[i]
          g += imgData[i + 1]
          b += imgData[i + 2]
        }
        r = Math.round(r / (imgData.length / 4))
        g = Math.round(g / (imgData.length / 4))
        b = Math.round(b / (imgData.length / 4))
        this.drawRect(x, y, this.squareEdgeLength, this.squareEdgeLength, `rgb(${r}, ${g}, ${b})`, 2, `rgb(${r}, ${g}, ${b})`)
      },
      // 添加文字
      addText () {
        this.resetClickStatus()
        this.isText = true
        console.log('添加文字')
      },
      // 裁剪
      tailor () {
        this.resetClickStatus()
        this.isTailor = true
        console.log('裁剪')
      } ,
      // 旋转
      rotate () {
        // if (this.angle === 360) {
        //   this.angle = 90
        // } else {
        //   this.angle += 90
        // }
        // if ([90, 270].includes(this.angle)) {
        //   this.canvas.setAttribute('width', this.image.height)
        //   this.canvas.setAttribute('height', this.image.width)
        // } else {
        //   this.canvas.setAttribute('width', this.image.width)
        //   this.canvas.setAttribute('height', this.image.height)
        // }
        const x = this.image.width / 2
        const y = this.image.height / 2
        this.context.clearRect(0,0, this.canvas.width, this.canvas.height)  // 清理画布内容
        this.context.translate(x, y)
        this.context.rotate(90 * Math.PI / 180)
        this.context.translate(-x, -y)
        this.context.drawImage(this.image, 0, 0)
      },
      resetClickStatus () {
        this.isMasic = false
        this.isText = false
        this.isTailor = false
        this.isTranslate = false
      },
      exportImg () {
        this.resetClickStatus()
        const exportUrl = this.canvas.toDataURL("image/jpeg")
        let a = document.createElement('a')
        a.setAttribute('download', '')
        a.href = exportUrl
        document.body.appendChild(a)
        a.click()
      }
    }
  }
</script>

<style scoped lang="less">
.operations {
  width: 1200px;
  margin: 0 auto;
  ul {
    display: flex;
    align-items: center;
    margin-bottom: 30px;
    li {
      list-style: none;
      margin-right: 20px;
      cursor: pointer;
    }
  }
}
.img-wrap {
  display: block;
  margin: 0 auto;
}
</style>

效果图如下:

canvas实现图片马赛克的示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3解决移动页面上点击链接触发色块的问题
Jun 03 HTML / CSS
详解CSS3 弹性布局快速入门
Jun 06 HTML / CSS
HTML+CSS3 模仿Windows7 桌面效果
Jun 17 HTML / CSS
CSS3图片旋转特效(360/60/-360度)
Oct 10 HTML / CSS
CSS3实例分享--超炫checkbox复选框和radio单选框
Sep 01 HTML / CSS
纯CSS3发光分享按钮的实现教程
Sep 06 HTML / CSS
CSS3中Animation属性的使用详解
Aug 06 HTML / CSS
详解CSS3 filter:drop-shadow滤镜与box-shadow区别与应用
Aug 24 HTML / CSS
HTML5的结构和语义(2):结构
Oct 17 HTML / CSS
整理HTML5中表单的常用属性及新属性
Feb 19 HTML / CSS
amazeui页面分析之登录页面的示例代码
Aug 25 HTML / CSS
新的CSS 伪类函数 :is() 和 :where()示例详解
Aug 05 HTML / CSS
HTML5 拖拽批量上传文件的示例代码
Mar 28 #HTML / CSS
利用html5 canvas动态画饼状图的示例代码
Apr 02 #HTML / CSS
简单聊聊H5的pushState与replaceState的用法
Apr 03 #HTML / CSS
如何使用localstorage代替cookie实现跨域共享数据问题
Apr 18 #HTML / CSS
Html5 localStorage入门教程
Apr 26 #HTML / CSS
在HTML5 canvas里用卷积核进行图像处理的方法
May 02 #HTML / CSS
HTML5新增的标签和属性归纳总结
May 02 #HTML / CSS
You might like
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
php解决约瑟夫环示例
2014/04/09 PHP
php中使用key,value,current,next和prev函数遍历数组的方法
2015/03/17 PHP
php验证码生成器
2017/05/24 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
tp5.1框架数据库子查询操作实例分析
2020/05/26 PHP
js 全兼容可高亮二级缓冲折叠菜单
2010/06/04 Javascript
JavaScript中的toDateString()方法使用详解
2015/06/12 Javascript
Backbone.js的一些使用技巧
2015/07/01 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
2016/05/19 Javascript
归纳下js面向对象的几种常见写法总结
2016/08/24 Javascript
手机端点击图片放大特效PhotoSwipe.js插件实现
2016/08/24 Javascript
JS对象与json字符串相互转换实现方法示例
2018/06/14 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
vue修改对象的属性值后页面不重新渲染的实例
2018/08/09 Javascript
nodejs使用async模块同步执行的方法
2019/03/02 NodeJs
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
JavaScript位置参数实现原理及过程解析
2020/09/14 Javascript
原生js实现自定义难度的扫雷游戏
2021/01/22 Javascript
Python fileinput模块使用介绍
2014/11/30 Python
Python中map和列表推导效率比较实例分析
2015/06/17 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
tensorflow:指定gpu 限制使用量百分比,设置最小使用量的实现
2020/02/06 Python
Python 实现二叉查找树的示例代码
2020/12/21 Python
AmazeUI 平滑滚动效果的示例代码
2020/08/20 HTML / CSS
Ray-Ban雷朋美国官网:全球领先的太阳眼镜品牌
2016/07/20 全球购物
西班牙英格列斯百货英国官网:El Corte Inglés英国
2017/10/30 全球购物
美国家庭鞋店:Shoe Sensation
2019/09/27 全球购物
房地产项目策划书
2014/02/05 职场文书
小摄影师教学反思
2014/04/27 职场文书
党员教师一句话承诺
2014/05/30 职场文书
团干部培训班心得体会
2016/01/06 职场文书
Java数据结构之链表相关知识总结
2021/06/18 Java/Android
Python3.10的一些新特性原理分析
2021/09/15 Python
python高温预警数据获取实例
2022/07/23 Python