Эффект осколков для изображения с помощью JS

Для слайдеров используется множество эффектов, их все сосчитать сложно, не то чтобы представить, но мы бы хотели отметить один небольшой эффект, который создает иллюзию разбитого стекла, изображение будет хаотично дробиться и постепенно исчезать, создавая при этом небольшой эффект объемности и полета осколков стекла вниз, при этом старое изображение будет замещаться новым. Такой эффект смотрится кустарно, но мы не могли его не заметить, и не показать его реализацию, возможно вы найдете ему рациональное применение.

Скачать файл: effect-fragment-to-image-with-help-js.zip [0 b] (cкачиваний: 10)


Эпицентром дробления стекла будет место нажатия кнопкой мыши, именно от этой точки будет происходить процесс разрушения и волна осколков.

Эффект осколков для изображения с помощью JS


Так как вывод изображения предусматривает только строчку с параметром container, то весь процесс дробления будет реализован с помощью функций js:

1
const TWO_PI = Math.PI * 2;
2
var images = [],
3
imageIndex = 0;
4
var image,
5
imageWidth = 768,
6
imageHeight = 485;
7
var vertices = [],
8
indices = [],
9
fragments = [];
10
var container = document.getElementById('container');
11
var clickPosition = [imageWidth * 0.5, imageHeight * 0.5];
12
window.onload = function() {
13
TweenMax.set(container, {perspective:500});
14
// images from reddit/r/wallpapers
15
var urls = [
16
'https:175711/crayon.jpg',
17
'https:175711/spaceship.jpg',
18
'https:175711/dj.jpg',
19
'https:175711/chicken.jpg'
20
],
21
image,
22
loaded = 0;
23
images[0] = image = new Image();
24
image.onload = function() {
25
if (++loaded === 1) {
26
imagesLoaded();
27
for (var i = 1; i < 4; i++) {
28
images[i] = image = new Image();
29
image.src = urls[i];
30
}
31
}
32
};
33
image.src = urls[0];
34
};
35
function imagesLoaded() {
36
placeImage(false);
37
triangulate();
38
shatter();
39
}
40
function placeImage(transitionIn) {
41
image = images[imageIndex];
42
if (++imageIndex === images.length) imageIndex = 0;
43
image.addEventListener('click', imageClickHandler);
44
container.appendChild(image);
45
if (transitionIn !== false) {
46
TweenMax.fromTo(image, 0.75, {y:-1000}, {y:0, ease:Back.easeOut});
47
}
48
}
49
function imageClickHandler(event) {
50
var box = image.getBoundingClientRect(),
51
top = box.top,
52
left = box.left;
53
clickPosition[0] = event.clientX - left;
54
clickPosition[1] = event.clientY - top;
55
triangulate();
56
shatter();
57
}
58
function triangulate() {
59
var rings = [
60
{r:50, c:12},
61
{r:150, c:12},
62
{r:300, c:12},
63
{r:1200, c:12} // very large in case of corner clicks
64
],
65
x,
66
y,
67
centerX = clickPosition[0],
68
centerY = clickPosition[1];
69
vertices.push([centerX, centerY]);
70
rings.forEach(function(ring) {
71
var radius = ring.r,
72
count = ring.c,
73
variance = radius * 0.25;
74
for (var i = 0; i < count; i++) {
75
x = Math.cos((i / count) * TWO_PI) * radius + centerX + randomRange(-variance, variance);
76
y = Math.sin((i / count) * TWO_PI) * radius + centerY + randomRange(-variance, variance);
77
vertices.push([x, y]);
78
}
79
});
80
vertices.forEach(function(v) {
81
v[0] = clamp(v[0], 0, imageWidth);
82
v[1] = clamp(v[1], 0, imageHeight);
83
});
84
indices = Delaunay.triangulate(vertices);
85
}
86
function shatter() {
87
var p0, p1, p2,
88
fragment;
89
var tl0 = new TimelineMax({onComplete:shatterCompleteHandler});
90
for (var i = 0; i < indices.length; i += 3) {
91
p0 = vertices[indices[i + 0]];
92
p1 = vertices[indices[i + 1]];
93
p2 = vertices[indices[i + 2]];
94
fragment = new Fragment(p0, p1, p2);
95
var dx = fragment.centroid[0] - clickPosition[0],
96
dy = fragment.centroid[1] - clickPosition[1],
97
d = Math.sqrt(dx * dx + dy * dy),
98
rx = 30 * sign(dy),
99
ry = 90 * -sign(dx),
100
delay = d * 0.003 * randomRange(0.9, 1.1);
101
fragment.canvas.style.zIndex = Math.floor(d).toString();
102
var tl1 = new TimelineMax();
103
tl1.to(fragment.canvas, 1, {
104
z:-500,
105
rotationX:rx,
106
rotationY:ry,
107
ease:Cubic.easeIn
108
});
109
tl1.to(fragment.canvas, 0.4,{alpha:0}, 0.6);
110
tl0.insert(tl1, delay);
111
fragments.push(fragment);
112
container.appendChild(fragment.canvas);
113
}
114
container.removeChild(image);
115
image.removeEventListener('click', imageClickHandler);
116
}
117
function shatterCompleteHandler() {
118
fragments.forEach(function(f) {
119
container.removeChild(f.canvas);
120
});
121
fragments.length = 0;
122
vertices.length = 0;
123
indices.length = 0;
124
placeImage();
125
}
126
function randomRange(min, max) {
127
return min + (max - min) * Math.random();
128
}
129
function clamp(x, min, max) {
130
return x < min ? min : (x > max ? max : x);
131
}
132
function sign(x) {
133
return x < 0 ? -1 : 1;
134
}
135
Fragment = function(v0, v1, v2) {
136
this.v0 = v0;
137
this.v1 = v1;
138
this.v2 = v2;
139
this.computeBoundingBox();
140
this.computeCentroid();
141
this.createCanvas();
142
this.clip();
143
};
144
Fragment.prototype = {
145
computeBoundingBox:function() {
146
var xMin = Math.min(this.v0[0], this.v1[0], this.v2[0]),
147
xMax = Math.max(this.v0[0], this.v1[0], this.v2[0]),
148
yMin = Math.min(this.v0[1], this.v1[1], this.v2[1]),
149
yMax = Math.max(this.v0[1], this.v1[1], this.v2[1]);
150
this.box ={
151
x:xMin,
152
y:yMin,
153
w:xMax - xMin,
154
h:yMax - yMin
155
};
156
},
157
computeCentroid:function() {
158
var x = (this.v0[0] + this.v1[0] + this.v2[0]) / 3,
159
y = (this.v0[1] + this.v1[1] + this.v2[1]) / 3;
160
this.centroid = [x, y];
161
},
162
createCanvas:function() {
163
this.canvas = document.createElement('canvas');
164
this.canvas.width = this.box.w;
165
this.canvas.height = this.box.h;
166
this.canvas.style.width = this.box.w + 'px';
167
this.canvas.style.height = this.box.h + 'px';
168
this.canvas.style.left = this.box.x + 'px';
169
this.canvas.style.top = this.box.y + 'px';
170
this.ctx = this.canvas.getContext('2d');
171
},
172
clip:function() {
173
this.ctx.translate(-this.box.x, -this.box.y);
174
this.ctx.beginPath();
175
this.ctx.moveTo(this.v0[0], this.v0[1]);
176
this.ctx.lineTo(this.v1[0], this.v1[1]);
177
this.ctx.lineTo(this.v2[0], this.v2[1]);
178
this.ctx.closePath();
179
this.ctx.clip();
180
this.ctx.drawImage(image, 0, 0);
181
}
182
};


Вот и все. Готово!

Отправить жалобу

Похожие публикации


Добавить комментарий

Кликните на изображение чтобы обновить код, если он неразборчив


Наверх