1. 概述
在Vue项目中,我们有时需要对图片进行特殊效果的处理。本文将介绍如何通过Vue实现图片的疑似油画和素描效果。
2. 疑似油画效果
要实现疑似油画效果,我们需要用到Node.js下的canvas和jscolor库。
2.1 安装jscolor库
Jscolor库是一个用于快速添加颜色选择器的JavaScript库。我们可以通过npm安装它。
npm install jscolor --save
2.2 引入jscolor库
将jscolor.js文件引入到Vue项目中:
// 在 Vue 项目中引入 jscolor.js
import '../node_modules/jscolor/jscolor.js'
2.3 声明并使用 canvas 组件
在模板中,添加canvas标签,声明canvas组件,并定义触摸事件
// 在 Vue 项目模板中声明 canvas 组件
<template>
<div>
<canvas ref="canvas"></canvas>
</div>
</template>
<script>
export default {
mounted () {
// 绑定触摸事件
this.$refs.canvas.addEventListener('touchmove', this.touchMove)
},
methods: {
touchMove (event) {
// 禁用默认行为
event.preventDefault()
// 获取触摸屏上第一个手指的触摸对象
const touch = event.touches[0]
// TODO: 在此添加处理代码
}
}
}
</script>
2.4 处理图片
我们可以通过以下步骤将图片处理成疑似油画效果:
获取图片
创建画布
将图片渲染到画布中
使用JavaScript中的ImageData对象,扫描画布像素,修改像素点的颜色
将修改后的像素点重新渲染到画布中
touchMove (event) {
// 禁用默认行为
event.preventDefault()
// 获取触摸屏上第一个手指的触摸对象
const touch = event.touches[0]
// 获取canvas元素
const canvas = this.$refs.canvas
// 创建画布
const ctx = canvas.getContext('2d')
// 加载图片到画布中
const img = new Image()
img.src = 'your-image.jpg'
img.onload = function () {
// 设置画布大小为图片尺寸大小
canvas.width = img.width
canvas.height = img.height
// 将图片渲染到画布上,原始位置是 0, 0
ctx.drawImage(img, 0, 0)
// 获取ImageData对象,这包含了图片各个像素点的颜色值
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
// 遍历每一个像素点
for (let i = 0; i < imageData.data.length; i += 4) {
// 将 R、G、B 三个颜色值转换成 HSL 值
const hsl = this.rgbToHsl(imageData.data[i], imageData.data[i + 1], imageData.data[i + 2])
// 加上一定的 offset,增加曝光度
hsl.l += 0.2
// 转换回 RGB 值
const rgb = this.hslToRgb(hsl.h, hsl.s, hsl.l)
// 设置像素点的新颜色
imageData.data[i] = rgb.r
imageData.data[i + 1] = rgb.g
imageData.data[i + 2] = rgb.b
}
// 把修改后的 ImageData 对象重新绘制到画布上
ctx.putImageData(imageData, 0, 0)
}
},
rgbToHsl (r, g, b) {
r /= 255, g /= 255, b /= 255
const max = Math.max(r, g, b), min = Math.min(r, g, b)
let h, s, l = (max + min) / 2
if (max === min) {
h = s = 0 // achromatic
} else {
const d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break
case g: h = (b - r) / d + 2; break
case b: h = (r - g) / d + 4; break
}
h /= 6
}
return { h, s, l }
},
hslToRgb (h, s, l) {
let r, g, b
if (s === 0) {
r = g = b = l // achromatic
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1
if (t > 1) t -= 1
if (t < 1 / 6) return p + (q - p) * 6 * t
if (t < 1 / 2) return q
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
return p
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
const p = 2 * l - q
r = hue2rgb(p, q, h + 1 / 3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1 / 3)
}
return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }
}
3. 疑似素描效果
要实现疑似素描效果,我们需要用到Node.js下的canvas和StackBlur库。
3.1 安装StackBlur库
StackBlur库可以对图片进行高斯模糊处理。我们可以通过npm安装它。
npm install stackblur-canvas --save
3.2 引入StackBlur库
将stackblur.js文件引入到Vue项目中:
// 在 Vue 项目中引入 stackblur.js
import '../node_modules/stackblur-canvas/dist/stackblur.min.js'
3.3 处理图片
我们可以通过以下步骤将图片处理成疑似素描效果:
获取图片
创建画布
将图片渲染到画布中
将画布的像素点转换成黑白像素点
使用 StackBlur 库进行高斯模糊处理
合并黑白像素点和高斯模糊后的像素点
touchMove (event) {
// 禁用默认行为
event.preventDefault()
// 获取触摸屏上第一个手指的触摸对象
const touch = event.touches[0]
// 获取canvas元素
const canvas = this.$refs.canvas
// 创建画布
const ctx = canvas.getContext('2d')
// 加载图片到画布中
const img = new Image()
img.src = 'your-image.jpg'
img.onload = function () {
// 设置画布大小为图片尺寸大小
canvas.width = img.width
canvas.height = img.height
// 将图片渲染到画布上,原始位置是 0, 0
ctx.drawImage(img, 0, 0)
// 获取ImageData对象,这包含了图片各个像素点的颜色值
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
// 遍历每一个像素点,将其转换为黑白
for (let i = 0; i < imageData.data.length; i += 4) {
const grayscale = (0.299 * imageData.data[i] + 0.587 * imageData.data[i + 1] + 0.114 * imageData.data[i + 2])
imageData.data[i] = grayscale // red
imageData.data[i + 1] = grayscale // green
imageData.data[i + 2] = grayscale // blue
}
// 使用 StackBlur 库进行高斯模糊处理
StackBlur.canvasRGBA(canvas, 0, 0, canvas.width, canvas.height, 10)
// 合并黑白像素点和高斯模糊后的像素点
const finalImageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
for (let i = 0; i < imageData.data.length; i += 4) {
finalImageData.data[i] = imageData.data[i] + (255 - imageData.data[i]) * 0.6 // red
finalImageData.data[i + 1] = imageData.data[i + 1] + (255 - imageData.data[i + 1]) * 0.6 // green
finalImageData.data[i + 2] = imageData.data[i + 2] + (255 - imageData.data[i + 2]) * 0.6 // blue
}
ctx.putImageData(finalImageData, 0, 0)
}
},
4. 总结
通过本文的介绍,我们可以发现,通过Vue实现图片特效并不是一件很难的事情。通过一些开源库的使用,我们可以快速、简便地实现图片的各种特效,丰富我们应用的用户体验。