1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+
4+ < head >
5+ < meta charset ="UTF-8 ">
6+ < meta http-equiv ="X-UA-Compatible " content ="IE=edge ">
7+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
8+ < title > Document</ title >
9+ </ head >
10+
11+ < body >
12+ < canvas id ="drawHeart "> </ canvas >
13+ </ body >
14+ < script >
15+ const canvas = document . getElementById ( 'drawHeart' ) ;
16+ const ctx = canvas . getContext ( '2d' ) ;
17+ let wW = window . innerWidth ;
18+ let wH = window . innerHeight ;
19+ const num = 100 ;
20+ const hearts = [ ] ;
21+ const heartImage = new Image ( ) ;
22+ heartImage . src = 'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><path id="heart" d="M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z" fill="red"/></svg>' ;
23+ class Heart {
24+ constructor ( type ) {
25+ this . type = type ;
26+ // 初始化生成范围
27+ this . x = Math . random ( ) * wW ;
28+ this . y = Math . random ( ) * wH ;
29+ this . opacity = Math . random ( ) * .5 + .5 ;
30+ // 偏移量
31+ this . vel = {
32+ x : ( Math . random ( ) - .5 ) * 5 ,
33+ y : ( Math . random ( ) - .5 ) * 5
34+ }
35+ this . initialW = wW * .5 ;
36+ this . initialH = wH * .5 ;
37+ // 缩放比例
38+ this . targetScale = Math . random ( ) * .15 + .02 ; // 最小0.02
39+ this . scale = Math . random ( ) * this . targetScale ;
40+ // 文字位置
41+ this . fx = Math . random ( ) * wW ;
42+ this . fy = Math . random ( ) * wH ;
43+ this . fs = Math . random ( ) * 10 ;
44+ this . text = getText ( ) ;
45+ this . fvel = {
46+ x : ( Math . random ( ) - .5 ) * 5 ,
47+ y : ( Math . random ( ) - .5 ) * 5 ,
48+ f : ( Math . random ( ) - .5 ) * 2
49+ }
50+ }
51+ draw ( ) {
52+ ctx . save ( ) ;
53+ ctx . globalAlpha = this . opacity ;
54+ ctx . drawImage ( heartImage , this . x , this . y , this . width , this . height ) ;
55+ // ctx.scale(this.scale + 1, this.scale + 1);
56+ if ( ! this . type ) {
57+ // 设置文字属性
58+ ctx . fillStyle = getColor ( ) ;
59+ ctx . font = 'italic ' + this . fs + 'px sans-serif' ;
60+ // 填充字符串
61+ ctx . fillText ( this . text , this . fx , this . fy ) ;
62+ }
63+ ctx . restore ( ) ;
64+ }
65+ update ( ) {
66+ this . x += this . vel . x ;
67+ this . y += this . vel . y ;
68+ if ( this . x - this . width > wW || this . x + this . width < 0 ) {
69+ // 重新初始化位置
70+ this . scale = 0 ;
71+ this . x = Math . random ( ) * wW ;
72+ this . y = Math . random ( ) * wH ;
73+ }
74+ if ( this . y - this . height > wH || this . y + this . height < 0 ) {
75+ // 重新初始化位置
76+ this . scale = 0 ;
77+ this . x = Math . random ( ) * wW ;
78+ this . y = Math . random ( ) * wH ;
79+ }
80+ // 放大
81+ this . scale += ( this . targetScale - this . scale ) * .1 ;
82+ this . height = this . scale * this . initialH ;
83+ this . width = this . height * 1.4 ;
84+ // -----文字-----
85+ this . fx += this . fvel . x ;
86+ this . fy += this . fvel . y ;
87+ this . fs += this . fvel . f ;
88+ if ( this . fs > 50 ) {
89+ this . fs = 2 ;
90+ }
91+ if ( this . fx - this . fs > wW || this . fx + this . fs < 0 ) {
92+ // 重新初始化位置
93+ this . fx = Math . random ( ) * wW ;
94+ this . fy = Math . random ( ) * wH ;
95+ }
96+ if ( this . fy - this . fs > wH || this . fy + this . fs < 0 ) {
97+ // 重新初始化位置
98+ this . fx = Math . random ( ) * wW ;
99+ this . fy = Math . random ( ) * wH ;
100+ }
101+ }
102+ }
103+ function getText ( ) {
104+ const val = Math . random ( ) * 10 ;
105+ if ( val > 1 && val <= 3 ) {
106+ return 'always' ;
107+ } else if ( val > 3 && val <= 5 ) {
108+ return 'zzy' ;
109+ } else if ( val > 5 && val <= 8 ) {
110+ return 'taylor swift' ;
111+ } else {
112+ return 'I Love You' ;
113+ }
114+ }
115+ function getColor ( ) {
116+ const val = Math . random ( ) * 10 ;
117+ if ( val > 0 && val <= 1 ) {
118+ return '#00f' ;
119+ } else if ( val > 1 && val <= 2 ) {
120+ return '#f00' ;
121+ } else if ( val > 2 && val <= 3 ) {
122+ return '#0f0' ;
123+ } else if ( val > 3 && val <= 4 ) {
124+ return '#368' ;
125+ } else if ( val > 4 && val <= 5 ) {
126+ return '#666' ;
127+ } else if ( val > 5 && val <= 6 ) {
128+ return '#333' ;
129+ } else if ( val > 6 && val <= 7 ) {
130+ return '#f50' ;
131+ } else if ( val > 7 && val <= 8 ) {
132+ return '#e96d5b' ;
133+ } else if ( val > 8 && val <= 9 ) {
134+ return '#5be9e9' ;
135+ } else {
136+ return '#d41d50' ;
137+ }
138+ }
139+ function init ( ) {
140+ canvas . width = wW ;
141+ canvas . height = wH ;
142+ for ( let i = 0 ; i < num ; i ++ ) {
143+ hearts . push ( new Heart ( i % 5 ) ) ;
144+ }
145+ render ( ) ;
146+ }
147+
148+ function render ( ) {
149+ ctx . clearRect ( 0 , 0 , wW , wH ) ;
150+ for ( let i = 0 ; i < hearts . length ; i ++ ) {
151+ hearts [ i ] . draw ( ) ;
152+ hearts [ i ] . update ( ) ;
153+ }
154+ setTimeout ( render , 60 ) ;
155+ }
156+
157+ init ( ) ;
158+ window . addEventListener ( 'resize' , function ( ) {
159+ canvas . width = wW = window . innerWidth ;
160+ canvas . height = wH = window . innerHeight ;
161+ } ) ;
162+ </ script >
163+
164+ </ html >
0 commit comments