1. Vue中图片的变形效果
Vue中使用CSS的transform属性可以实现图片的变形效果。比如我们可以通过旋转、缩放和扭曲等方式实现各种效果。我们可以通过Vue组件来实现这些效果。以下是实现图片变形效果的代码示例:
<template>
<div class="wrapper">
<img :src="imageUrl" :style="{transform: 'rotate('+rotateVal+'deg) scale('+scaleVal+') skew('+skewVal+'rad)'}">
</div>
</template>
<script>
export default {
data () {
return {
imageUrl: 'image_url',
rotateVal: 0,
scaleVal: 1,
skewVal: 0
}
},
methods: {
rotateImg () {
this.rotateVal += 45
},
scaleImg () {
this.scaleVal += 0.1
},
skewImg () {
this.skewVal += 0.1
}
}
}
</script>
<style scoped>
.wrapper {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
width: 300px;
}
img {
transition: all 0.5s ease-in-out;
}
</style>
1.1 代码解释
上述代码中,我们创建了一个Vue组件,该组件接收一个图片链接,并通过CSS的transform属性进行变形。我们在组件中定义了三个变量rotateVal、scaleVal、skewVal来控制绕Z轴旋转、缩放和扭曲的值。在组件中定义了三个方法rotateImg、scaleImg、skewImg用来分别改变这三个变量的值。我们在模板中通过:style来绑定transform属性,并把三个变量的值分别传入。CSS样式的部分我们定义了一个包装容器wrapper和图片,我们采用flex布局来垂直居中和水平居中的效果,并在img标签上设置了transition来让图片产生旋转、缩放和扭曲效果的平滑过渡。
在浏览器中预览组件后,我们可以通过调用rotateImg、scaleImg、skewImg方法来改变变量的值,从而控制图片的变形效果。由于我们在模板中绑定了transform属性,该属性的值会根据rotateVal、scaleVal、skewVal的变化而改变,从而产生变形效果。
2. Vue中如何实现图片的弯曲和扭转效果
2.1 使用SVG来实现图片的弯曲和扭转
SVG(Scalable Vector Graphics)是一种基于XML的矢量图形格式,具有可缩放、可交互、动画效果丰富的特点。我们可以使用SVG来实现图片的弯曲和扭转效果。
下面是一个使用SVG来实现图片弯曲效果的代码示例:
<template>
<div class="wrapper">
<svg :viewBox="viewBox">
<defs>
<pattern id="image" x="0" y="0" width="1" height="1">
<image :href="imageUrl" width="100%" height="100%"/>
</pattern>
</defs>
<path :d="d" fill="url(#image)"></path>
</svg>
</div>
</template>
<script>
export default {
data () {
return {
imageUrl: 'image_url',
viewBox: '0 0 500 500',
d: 'M-30,50 C-20,-30 20,-30 30,50 L30,500 L-30,500 Z'
}
}
}
</script>
<style scoped>
.wrapper {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
width: 300px;
}
</style>
2.1.1 代码解释
在上述代码中,我们创建了一个Vue组件,该组件使用SVG来实现图片的弯曲效果。在模板中,我们采用了svg和path标签来实现。我们使用defs标签来定义一个pattern元素,并在其中定义图片链接。我们将pattern元素的Id设置为"image"。接下来,我们在path标签中使用fill属性将图片填充到路径中。在data中定义了三个变量imageUrl、viewBox、d,imageUrl代表图片的链接地址,viewBox属性表示当前SVG中用户坐标系的范围,d属性定义了弯曲路径的坐标。在CSS样式定义区域我们将包装容器设置为了flex项并垂直居中和水平居中。
在SVG中,我们没有采用CSS的Transform属性,而是直接使用d属性来变换图片。d属性代表绘制路径的命令和坐标参数,我们在Path标签中使用该属性实现图片的弯曲效果。
2.1.2 弯曲路径的坐标解释
在上述代码中,我们使用了如下路径坐标来产生弯曲效果:
-30,50 C-20,-30 20,-30 30,50 L30,500 L-30,500 Z
坐标使用形式为 M x,y, C x1,y1, x2,y2, x,y,表示起点和三次Bezier曲线绘画。其中,C指定了两个控制点和一个终点。控制点x1,y1到起点x,y之间的连线称为第一个切线,控制点x2,y2到终点x,y之间的连线成为第二个切线。而L指令则是绘制一条直线连接起点和终点,这里L指令可省略,表示默认连接终点和起点。最后,Z指令表示绘制一条从当前点到路径的起点的线段,并且将其闭合,即完成所有绘画。
2.1.3 实现图片扭曲效果
对于图片扭曲效果的实现,我们可以使用SVG中的mask标签结合path标签实现。以下是一个使用SVG来实现图片扭曲效果的代码示例:
<template>
<div class="wrapper">
<svg :viewBox="viewBox">
<path :d="d" fill="url(#image)"></path>
<mask id="mask" x="0" y="0">
<path :d="d2" fill="white" />
</mask>
<rect :mask="'url(#mask)'" x="0" y="0" :width="500" :height="500"/>
</svg>
</div>
</template>
<script>
export default {
data () {
return {
imageUrl: 'image_url',
viewBox: '0 0 500 500',
d: 'M50,30 C-30,20 -30,-20 50,-30 L500,-30 L500,30 Z',
d2: 'M0,0 C250,100 250,400 0,500'
}
}
}
</script>
<style scoped>
.wrapper {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
width: 300px;
}
</style>
2.1.4 代码解释
在上述代码中,我们将图片绘制到SVG中,并对其进行遮罩处理来实现扭曲效果。我们在path标签中通过fill属性将图片链接到路径中。在遮罩mask中,我们通过d2属性定义扭曲路径的坐标,并在path标签中添加fill属性并设置为白色来生成一个遮罩蒙层。在rect标签中使用mask设置路径上蒙层生效的区域,从而实现扭曲效果。在CSS样式定义区域,我们同样采用flex布局将容器垂直居中和水平居中。
绘制扭曲的路径,我们使用了如下坐标来实现:
M0,0 C250,100 250,400 0,500
我们首先通过M指令标志出了路径的起点为(0,0),然后使用了C指令来指定了三个控制点(250,100)、(250,400)、(0,500),这里我们使用Bezier曲线来绘制拟合的扭曲路径,容易发现这是一个弧形路径。
2.2 使用WebGL来实现图片的弯曲和扭转
除了使用SVG来实现图片弯曲和扭曲效果以外,我们还可以使用WebGL(Web Graphics Library)来实现。WebGL是一种全新的接口,可以在浏览器中直接访问GPU,使用OpenGL ES(移动平台上的OpenGL标准)的操作,提供了高性能、低延迟的图形渲染能力。
下面是一个使用WebGL来实现图片弯曲和扭曲效果的代码示例:
<template>
<canvas ref="canvas"></canvas>
</template>
<script>
export default {
mounted() {
const canvas = this.$refs.canvas
const gl = canvas.getContext('webgl')
gl.viewport(0, 0, canvas.width, canvas.height)
const image = new Image()
const program = gl.createProgram()
const vertexShader = `
attribute vec2 position;
uniform vec2 resolution;
void main() {
vec2 normalized = position / resolution * 2.0 - 1.0;
gl_Position = vec4(normalized, 0.0, 1.0);
}
`
const fragmentShader = `
precision highp float;
uniform vec2 mouse;
uniform float time;
uniform sampler2D img;
uniform vec2 resolution;
const float pi = 3.14159265358979323846;
void main() {
vec2 uv = gl_FragCoord.xy / resolution.xy;
uv -= 0.5;
uv.x *= resolution.x / resolution.y;
float scale = 0.15;
float angle = 0.2;
float twist = 0.1;
vec2 distortedUV = uv;
distortedUV.x += sin(uv.y * pi * scale + time * twist) * angle * mouse.x;
distortedUV.y += sin(uv.x * pi * scale + time * twist) * angle * mouse.y;
vec4 col = mix(vec4(1.0, 1.0, 1.0, 1.0), texture2D(img, distortedUV), 0.5);
gl_FragColor = col;
}
`
function compileShader(shaderSource, shaderType) {
const shader = gl.createShader(shaderType)
gl.shaderSource(shader, shaderSource)
gl.compileShader(shader)
return shader
}
function linkProgram(vertex, fragment) {
gl.attachShader(program, vertex)
gl.attachShader(program, fragment)
gl.linkProgram(program)
return program
}
image.onload = function () {
canvas.width = image.width
canvas.height = image.height
gl.useProgram(linkProgram(
compileShader(vertexShader, gl.VERTEX_SHADER),
compileShader(fragmentShader, gl.FRAGMENT_SHADER)
))
const positionLocation = gl.getAttribLocation(program, 'position')
const resolutionLocation = gl.getUniformLocation(program, 'resolution')
const imgLocation = gl.getUniformLocation(program, 'img')
const mouseLocation = gl.getUniformLocation(program, 'mouse')
const timeLocation = gl.getUniformLocation(program, 'time')
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0,
canvas.width, 0,
0, canvas.height,
0, canvas.height,
canvas.width, 0,
canvas.width, canvas.height
]), gl.STATIC_DRAW)
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.enableVertexAttribArray(positionLocation)
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)
gl.uniform2f(resolutionLocation, canvas.width, canvas.height)
gl.uniform2f(mouseLocation, 0, 0)
gl.uniform1f(timeLocation, 0)
gl.activeTexture(gl.TEXTURE0);
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
let mouseX, mouseY;
function onMouseMove(e) {
const { clientX, clientY } = e;
const canvasRect = canvas.getBoundingClientRect();
mouseX = clientX - canvasRect.left;
mouseY = canvasRect.height - (clientY - canvasRect.top);
}
canvas.addEventListener('mousemove', onMouseMove);
let startTime = 0
function loop(now) {
if (!startTime) {
startTime = now;
}
const elapsedTime = (now - startTime) / 1000;
gl.uniform1f(timeLocation, elapsedTime)
gl.uniform2f(mouseLocation, mouseX / canvas.width - 0.5, mouseY / canvas.height - 0.5)
gl.drawArrays(gl.TRIANGLES, 0, 6)
window.requestAnimationFrame(loop)
}
window.requestAnimationFrame(loop)
}
image.src = this.imageUrl
},
data () {
return {
imageUrl: 'image_url'
}
}
}
</script>
<style scoped>
canvas {
display: block;
margin: 0 auto;
}
</style>
2.2.1 代码解释
在上述代码中,我们使用了WebGL来实现图片弯曲和扭曲效果。WebGL是一种近似于OpenGL的图形库,并且非常适合在浏览器中用于3D图形渲染。
在组件中,我们在mounted生命周期中使用了canvas API来获取绘制上下文,并将图片加载到canvas中。我们定义了三个着色器,分别是顶点着色器、片元着色器、着色器链接。我们在顶点着色器中定义了两个变量position和resolution,并且设置了转换矩阵的计算方式。我们在片元着色器中定义了