js实现水墨特效
实现水墨特效的方法
水墨特效可以通过Canvas结合图像处理技术实现,以下是一种常见的实现方式:
使用Canvas处理图像
const canvas = document.createElement('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;
ctx.drawImage(img, 0, 0);
// 获取像素数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// 应用水墨效果
for(let i = 0; i < data.length; i += 4) {
// 灰度化
const gray = 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2];
// 增加对比度
const contrast = 1.5;
const factor = (259 * (contrast + 255)) / (255 * (259 - contrast));
const newColor = factor * (gray - 128) + 128;
// 应用水墨风格
const inkColor = newColor < 128 ? 0 : 255;
data[i] = inkColor;
data[i+1] = inkColor;
data[i+2] = inkColor;
}
ctx.putImageData(imageData, 0, 0);
document.body.appendChild(canvas);
};
水墨扩散效果实现
为了实现更真实的水墨扩散效果,可以添加模糊和边缘检测:
function applyInkEffect(canvas) {
const ctx = canvas.getContext('2d');
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
// 1. 灰度处理
tempCtx.drawImage(canvas, 0, 0);
const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
const data = imageData.data;
for(let i = 0; i < data.length; i += 4) {
const gray = 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2];
data[i] = data[i+1] = data[i+2] = gray;
}
tempCtx.putImageData(imageData, 0, 0);
// 2. 边缘检测
edgeDetection(tempCanvas);
// 3. 模糊处理
gaussianBlur(tempCanvas, 2);
ctx.drawImage(tempCanvas, 0, 0);
}
// 边缘检测函数示例
function edgeDetection(canvas) {
// Sobel算子实现...
}
// 高斯模糊函数示例
function gaussianBlur(canvas, radius) {
// 模糊算法实现...
}
使用WebGL实现高性能水墨效果
对于更复杂的水墨渲染,可以使用WebGL:
const vertexShaderSource = `
attribute vec2 a_position;
varying vec2 v_texCoord;
void main() {
gl_Position = vec4(a_position, 0, 1);
v_texCoord = a_position * 0.5 + 0.5;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D u_image;
void main() {
vec4 color = texture2D(u_image, v_texCoord);
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
vec3 inkColor = vec3(1.0 - smoothstep(0.3, 0.7, gray));
gl_FragColor = vec4(inkColor, 1.0);
}
`;
// WebGL初始化代码...
水墨动画效果
实现水墨逐渐扩散的动画效果:
function animateInkSpread(canvas) {
const ctx = canvas.getContext('2d');
let radius = 0;
const maxRadius = Math.max(canvas.width, canvas.height) / 2;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 创建径向渐变模拟扩散
const gradient = ctx.createRadialGradient(
canvas.width/2, canvas.height/2, 0,
canvas.width/2, canvas.height/2, radius
);
gradient.addColorStop(0, 'rgba(0,0,0,0.8)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(canvas.width/2, canvas.height/2, radius, 0, Math.PI * 2);
ctx.fill();
radius += 2;
if(radius < maxRadius) {
requestAnimationFrame(draw);
}
}
draw();
}
以上方法提供了从简单到复杂的水墨特效实现方案,可以根据需求选择合适的实现方式。Canvas方法适合静态图像处理,WebGL适合高性能渲染,而动画方法可以创建动态水墨效果。







