├── create_a_love ├── digital-7_mono.ttf ├── css │ └── style.css ├── index.html └── js │ ├── function.js │ └── garden.js └── README.md /create_a_love/digital-7_mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MuYunyun/create/HEAD/create_a_love/digital-7_mono.ttf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### create 2 | 3 | It's a interesting project to create something. 4 | 5 | 6 | -------------------------------------------------------------------------------- /create_a_love/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #FFFFEE; 5 | font-size: 12px; 6 | overflow: auto; 7 | } 8 | 9 | #mainDiv{ 10 | width: 100%; 11 | height: 100%; 12 | } 13 | 14 | #loveHeart { 15 | float: left; 16 | width: 670px; 17 | height: 625px; 18 | } 19 | 20 | #garden { 21 | width: 100%; 22 | height: 100%; 23 | } 24 | 25 | #elapseClock { 26 | text-align: right; 27 | font-size: 18px; 28 | margin-top: 10px; 29 | margin-bottom: 10px; 30 | } 31 | 32 | #elapseClock .digit { 33 | font-family: "digit"; 34 | font-size: 36px; 35 | } 36 | 37 | #loveu { 38 | padding: 5px; 39 | font-size: 22px; 40 | margin-top: 80px; 41 | margin-right: 120px; 42 | text-align: right; 43 | display: none; 44 | } 45 | 46 | #loveu .signature { 47 | margin-top: 10px; 48 | font-size: 20px; 49 | font-style: italic; 50 | } 51 | 52 | #words { 53 | font-family: "sans-serif"; 54 | width: 500px; 55 | font-size: 24px; 56 | color: #666; 57 | } 58 | 59 | #messages{ 60 | display: none; 61 | } 62 | 63 | #code { 64 | float: left; 65 | width: 440px; 66 | color: #333; 67 | font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", "sans-serif"; 68 | font-size: 12px; 69 | } 70 | 71 | #code .string{ 72 | color: #2a36ff; 73 | } 74 | 75 | #code .keyword{ 76 | color: #7f0055; 77 | font-weight: bold; 78 | } 79 | 80 | #code .placeholder{ 81 | margin-left: 15px; 82 | } 83 | 84 | #code .space { 85 | margin-left: 7px; 86 | } 87 | 88 | #code .comments { 89 | color: #3f7f5f; 90 | } 91 | 92 | #errorMsg { 93 | width: 100%; 94 | text-align: center; 95 | font-size: 24px; 96 | position: absolute; 97 | top: 100px; 98 | left: 0px; 99 | } 100 | 101 | #copyright{ 102 | margin-top: 10px; 103 | text-align: center; 104 | width:100%; 105 | color:#666; 106 | } 107 | 108 | #copyright a{ 109 | color:#666; 110 | } 111 | -------------------------------------------------------------------------------- /create_a_love/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Our Love Story 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | /**
24 | * We are both programmers,
25 | * so I write some code to describe our stories.
26 | */
27 | Boy i = new Boy("Muyy");
28 | Girl u = new Gril("Poem");
29 | // Nov 2, 2017, I told you I love you.
30 | i.love(u);
31 | // Luckily, you accepted and became my girlfriend eversince.
32 | u.accepted();
33 | // Since then, I miss u every day.
34 | i.miss(u);
35 | // And take care of u and our love.
36 | i.takeCareOf(u);
37 | // You say that you won't be so easy to marry me.
38 | // So I keep waiting and I have confidence that you will.
39 | boolean isHesitate = true;
40 | while (isHesitate) {
41 | i.waitFor(u);
42 | // I think it is an important decision
43 | // and you should think it over.
44 | isHesitate = u.thinkOver();
45 | }
46 | // After a romantic wedding, we will live happily ever after.
47 | i.marry(u);
48 | i.liveHappilyWith(u);
49 |
50 |
51 | 52 |
53 |
54 | Poem, I have fallen in love with you for 55 |
56 |
57 |
58 | Love u forever and ever.
59 |
- Muyy
60 |
61 |
62 |
63 |
64 | 68 |
69 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /create_a_love/js/function.js: -------------------------------------------------------------------------------- 1 | let $window = $(window),garden; 2 | 3 | $(function () { 4 | // setup garden 5 | let $loveHeart = $("#loveHeart"), 6 | offsetX = $loveHeart.width() / 2, 7 | offsetY = $loveHeart.height() / 2 - 55, 8 | $garden = $("#garden"), 9 | gardenCanvas = $garden[0], 10 | gardenCtx = gardenCanvas.getContext("2d"); 11 | garden = new Garden(gardenCtx, gardenCanvas); 12 | gardenCanvas.width = $("#loveHeart").width(); 13 | gardenCanvas.height = $("#loveHeart").height(); 14 | gardenCtx.globalCompositeOperation = "lighter"; // 显示源图像 + 目标图像 15 | 16 | $("#content").css("width", $loveHeart.width() + $("#code").width()); 17 | $("#content").css("height", Math.max($loveHeart.height(), $("#code").height())); 18 | $("#content").css("margin-top", Math.max(($window.height() - $("#content").height()) / 2, 10)); // 垂直居中 19 | $("#content").css("margin-left", Math.max(($window.width() - $("#content").width()) / 2, 10)); // 水平居中 20 | 21 | // renderLoop 22 | setInterval(function () { 23 | garden.render(); 24 | }, Garden.options.growSpeed); 25 | }); 26 | 27 | // 返回爱心点的坐标 28 | function getHeartPoint(angle) { 29 | var t = angle / Math.PI; 30 | var x = 19.5 * (16 * Math.pow(Math.sin(t), 3)); 31 | var y = - 20 * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t)); 32 | return new Array(offsetX + x, offsetY + y); 33 | } 34 | 35 | // 爱心效果 36 | function startHeartAnimation() { 37 | var angle = 10; // 度数 38 | var heart = new Array(); 39 | var animationTimer = setInterval(function() { 40 | var bloom = getHeartPoint(angle); 41 | var draw = true; 42 | for (var i = 0; i < heart.length; i++) { // 防止首位的颜色过度叠加(具体的还没弄懂) 43 | var p = heart[i]; 44 | var distance = Math.sqrt(Math.pow(p[0] - bloom[0], 2) + Math.pow(p[1] - bloom[1], 2)); 45 | if (distance < Garden.options.bloomRadius.max * 1.3) { 46 | draw = false; 47 | break; 48 | } 49 | } 50 | if (draw) { 51 | heart.push(bloom); 52 | garden.createRandomBloom(bloom[0], bloom[1]); // 根据具体位置创建随机花朵; 53 | } 54 | if (angle >= 30) { 55 | clearInterval(animationTimer); 56 | showMessages(); 57 | } else { 58 | angle += 0.2; 59 | } 60 | }, 75); 61 | } 62 | 63 | // 模拟出打字效果 64 | (function($) { 65 | $.fn.typewriter = function() { 66 | this.each(function() { 67 | let $ele = $(this), 68 | str = $ele.html(), 69 | progress = 0; 70 | $ele.html(''); 71 | let timer = setInterval(function() { 72 | let current = str.substr(progress, 1); // 每次截取一个字符 73 | if (current === '<') { // 如果是<则找到对应的>,并增加相应的progress的值; 74 | progress = str.indexOf('>', progress) + 1; // 从<>的下一个开始 75 | } else { 76 | progress++; 77 | } 78 | // progress & 1 与运算 奇数 & 1 = 1,偶数 & 1 = 0; 79 | $ele.html(str.substring(0, progress) + (progress & 1 ? '_' : '')); // 模拟出打字'_'闪烁效果 80 | }, 75); 81 | }); 82 | return this; 83 | }; 84 | })(jQuery); 85 | 86 | function timeElapse(date) { 87 | var current = Date(); 88 | var seconds = (Date.parse(current) - Date.parse(date)) / 1000; 89 | var days = Math.floor(seconds / (3600 * 24)); 90 | seconds = seconds % (3600 * 24); 91 | var hours = Math.floor(seconds / 3600); 92 | if (hours < 10) { 93 | hours = "0" + hours; 94 | } 95 | seconds = seconds % 3600; 96 | var minutes = Math.floor(seconds / 60); 97 | if (minutes < 10) { 98 | minutes = "0" + minutes; 99 | } 100 | seconds = seconds % 60; 101 | if (seconds < 10) { 102 | seconds = "0" + seconds; 103 | } 104 | var result = "" + days + " days " + hours + " hours " + minutes + " minutes " + seconds + " seconds"; 105 | $('#elapseClock').html(result); 106 | } 107 | 108 | function showMessages() { 109 | adjustWordsPosition(); 110 | $('#messages').fadeIn(5000, function() { 111 | showLoveU(); 112 | }); 113 | } 114 | 115 | function adjustWordsPosition() { 116 | $('#words').css("position", "absolute"); 117 | $('#words').css("top", $("#garden").position().top + 195); 118 | $('#words').css("left", $("#garden").position().left + 70); 119 | } 120 | 121 | function adjustCodePosition() { 122 | $('#code').css("margin-top", ($('#garden').height() - $("#code").height()) / 2); 123 | } 124 | 125 | function showLoveU() { 126 | $('#loveu').fadeIn(3000); 127 | } 128 | -------------------------------------------------------------------------------- /create_a_love/js/garden.js: -------------------------------------------------------------------------------- 1 | function Vector(x, y) { 2 | this.x = x; 3 | this.y = y; 4 | }; 5 | 6 | Vector.prototype = { 7 | rotate: function (theta) { 8 | var x = this.x; 9 | var y = this.y; 10 | this.x = Math.cos(theta) * x - Math.sin(theta) * y; 11 | this.y = Math.sin(theta) * x + Math.cos(theta) * y; 12 | return this; 13 | }, 14 | mult: function (f) { 15 | this.x *= f; 16 | this.y *= f; 17 | return this; 18 | }, 19 | clone: function () { 20 | return new Vector(this.x, this.y); 21 | } 22 | }; 23 | 24 | function Petal(stretchA, stretchB, startAngle, angle, growFactor, bloom) { // 花瓣 25 | this.stretchA = stretchA; 26 | this.stretchB = stretchB; 27 | this.startAngle = startAngle; 28 | this.angle = angle; 29 | this.bloom = bloom; 30 | this.growFactor = growFactor; 31 | this.r = 1; 32 | this.isfinished = false; 33 | } 34 | 35 | Petal.prototype = { 36 | draw: function () { 37 | var ctx = this.bloom.garden.ctx; 38 | var v1, v2, v3, v4; 39 | v1 = new Vector(0, this.r).rotate(Garden.degrad(this.startAngle)); 40 | v2 = v1.clone().rotate(Garden.degrad(this.angle)); 41 | v3 = v1.clone().mult(this.stretchA); 42 | v4 = v2.clone().mult(this.stretchB); 43 | ctx.strokeStyle = this.bloom.c; // ? 44 | ctx.beginPath(); 45 | ctx.moveTo(v1.x, v1.y); 46 | ctx.bezierCurveTo(v3.x, v3.y, v4.x, v4.y, v2.x, v2.y); 47 | ctx.stroke(); 48 | }, 49 | render: function () { 50 | if (this.r <= this.bloom.r) { 51 | this.r += this.growFactor; 52 | this.draw(); 53 | } else { 54 | this.isfinished = true; 55 | } 56 | } 57 | } 58 | 59 | // flowers 60 | function Bloom(p, r, c, pc, garden) { 61 | this.p = p; 62 | this.r = r; 63 | this.c = c; 64 | this.pc = pc; 65 | this.petals = []; 66 | this.garden = garden; 67 | this.init(); 68 | this.garden.addBloom(this); 69 | }; 70 | 71 | Bloom.prototype = { 72 | draw: function () { 73 | var p, isfinished = true; 74 | this.garden.ctx.save(); 75 | this.garden.ctx.translate(this.p.x, this.p.y); 76 | for (var i = 0; i < this.petals.length; i++) { 77 | p = this.petals[i]; 78 | p.render(); 79 | isfinished *= p.isfinished; 80 | } 81 | this.garden.ctx.restore(); 82 | if (isfinished == true) { 83 | this.garden.removeBloom(this); 84 | } 85 | }, 86 | init: function () { 87 | var angle = 360 / this.pc; 88 | var startAngle = Garden.randomInt(0, 90); 89 | for (var i = 0; i < this.pc; i++) { 90 | this.petals.push(new Petal(Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max), Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max), startAngle + i * angle, angle, Garden.random(Garden.options.growFactor.min, Garden.options.growFactor.max), this)); 91 | } 92 | } 93 | } 94 | 95 | function Garden(ctx, element) { 96 | this.blooms = []; 97 | this.element = element; 98 | this.ctx = ctx; 99 | } 100 | 101 | Garden.prototype = { 102 | render: function () { 103 | for(let i = 0; i < this.blooms.length; i++) { 104 | this.blooms[i].draw(); 105 | } 106 | }, 107 | addBloom: function (b) { 108 | this.blooms.push(b); 109 | }, 110 | removeBloom: function (b) { 111 | let bloom; 112 | for (let i = 0; i < this.blooms.length; i++) { 113 | bloom = this.blooms[i]; 114 | if (bloom === b) { 115 | this.blooms.splice(i, 1); 116 | return this; 117 | } 118 | } 119 | }, 120 | createRandomBloom: function(x, y) { 121 | this.createBloom(x, y, Garden.randomInt(Garden.options.bloomRadius.min, Garden.options.bloomRadius.max), Garden.randomrgba(Garden.options.color.rmin, Garden.options.color.rmax, Garden.options.color.gmin, Garden.options.color.gmax, Garden.options.color.bmin, Garden.options.color.bmax, Garden.options.color.opacity), Garden.randomInt(Garden.options.petalCount.min, Garden.options.petalCount.max)); 122 | }, 123 | // x,y,半径,颜色,花盘数量 124 | createBloom: function (x, y, r, c, pc) { 125 | new Bloom(new Vector(x, y), r, c, pc, this); 126 | } 127 | } 128 | 129 | Garden.options = { 130 | petalCount: { // 花盘数量 131 | min: 8, 132 | max: 15 133 | }, 134 | petalStretch: { // 拉伸 135 | min: 0.1, 136 | max: 3 137 | }, 138 | growFactor: { // 因素 139 | min: 0.1, 140 | max: 1 141 | }, 142 | bloomRadius: { 143 | min: 8, 144 | max: 10 145 | }, 146 | growSpeed: 1000 / 60, // 花的生长速度; 147 | color: { 148 | rmin: 128, 149 | rmax: 255, 150 | gmin: 0, 151 | gmax: 128, 152 | bmin: 0, 153 | bmax: 128, 154 | opacity: 0.1 155 | } 156 | }; 157 | Garden.random = function (min, max) { 158 | return Math.random() * (max - min) + min; 159 | }; 160 | Garden.randomInt = function (min, max) { 161 | return Math.floor(Math.random() * (max - min + 1)) + min; 162 | }; 163 | Garden.circle = 2 * Math.PI; 164 | Garden.degrad = function (angle) { 165 | return Garden.circle / 360 * angle; 166 | }; 167 | Garden.raddeg = function (angle) { 168 | return angle / Garden.circle * 360; 169 | }; 170 | Garden.rgba = function (r, g, b, a) { 171 | return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; 172 | }; 173 | Garden.randomrgba = function (rmin, rmax, gmin, gmax, bmin, bmax, a) { 174 | var r = Math.round(Garden.random(rmin, rmax)); 175 | var g = Math.round(Garden.random(gmin, gmax)); 176 | var b = Math.round(Garden.random(bmin, bmax)); 177 | return Garden.rgba(r, g, b, a); 178 | } 179 | --------------------------------------------------------------------------------