小前端大能耐——Canvas与Javascript配合实现几个功能
时间:2014-07-22 22:59:53
收藏:0
阅读:400
1.粒子化
function Dot(X, Y, Z, R) { this.dx = X; this.dy = Y; this.dz = Z; this.tx = 0; this.ty = 0; this.tz = 0; this.z = Z; this.x = X; this.y = Y; this.r = R; this.paint = function() { context.save(); context.beginPath(); var scale = 250 / (250 + this.z); context.arc(canvas.width / 2 + (this.x - canvas.width / 2) * scale, canvas.height / 2 + (this.y - canvas.height / 2) * scale, this.r * scale, 0, 2 * Math.PI); context.fillStyle = "rgba(50,50,50," + scale + ")"; context.fill(); context.restore(); } } window.onload = function() { canvas = document.getElementsByTagName("canvas")[0]; context = canvas.getContext(‘2d‘); var dots = getimgData(‘program‘); dots.forEach(function(dot) { dot.tx = Math.random() * canvas.width; dot.ty = Math.random() * canvas.height; dot.tz = Math.random() * 250 * 2 - 250; dot.x = dot.tx; dot.y = dot.ty; dot.z = dot.tz; dot.paint(); }); var moving = false; var lastTime; var direction = true; function animate() { animateRunning = true; var thisTime = +new Date(); context.clearRect(0, 0, canvas.width, canvas.height); dots.forEach(function(dot) { if (direction) { if (Math.abs(dot.dx - dot.x) < 0.1 && Math.abs(dot.dy - dot.y) < 0.1 && Math.abs(dot.dz - dot.z) < 0.1) { if (thisTime - lastTime > 1000) direction = false; } else { dot.x += (dot.dx - dot.x) * 0.1; dot.y += (dot.dy - dot.y) * 0.1; dot.z += (dot.dz - dot.z) * 0.1; lastTime = +new Date(); } } else { if (Math.abs(dot.tx - dot.x) < 0.1 && Math.abs(dot.ty - dot.y) < 0.1 && Math.abs(dot.tz - dot.z) < 0.1) { moving = false; } else { dot.x += (dot.tx - dot.x) * 0.1; dot.y += (dot.ty - dot.y) * 0.1; dot.z += (dot.tz - dot.z) * 0.1; } } dot.paint(); }); if (moving) { if ("requestAnimationFrame" in window) { requestAnimationFrame(animate); } else if ("webkitRequestAnimationFrame" in window) { webkitRequestAnimationFrame(animate); } } } document.getElementById(‘startBtn‘).onclick = function() { if (moving) return; dots = getimgData(document.getElementById(‘name‘).value); direction = true; moving = true; dots.forEach(function(dot) { dot.tx = Math.random() * canvas.width; dot.ty = Math.random() * canvas.height; dot.tz = Math.random() * 250 * 2 - 250; dot.x = dot.tx; dot.y = dot.ty; dot.z = dot.tz; dot.paint(); }); animate(); } } function getimgData(text) { context.save(); context.font = "200px 微软雅黑 bold"; context.fillStyle = "rgba(255,255,255,1)"; context.textAlign = "center"; context.textBaseline = "middle"; context.fillText(text, canvas.width / 2, canvas.height / 2); context.restore(); var imgData = context.getImageData(0, 0, canvas.width, canvas.height); context.clearRect(0, 0, canvas.width, canvas.height); var dots = []; for (var y = 0; y < imgData.height; y += 6) { for (var x = 0; x < imgData.width; x += 6) { var i = (y * imgData.width + x) * 4; if (imgData.data[i] >= 255) { dots.push(new Dot(x - 3, y - 3, 0, 3)); } } } return dots; }
2.图片文字识别
<html> <head> <meta charset="UTF-8"> <title>文字识别</title> </head> <body> <canvas id="canvas" width="880" height="1500"></canvas> <script type="text/javascript"> var image = new Image(); image.src = ‘image.jpg‘; var stanData = {}; var lineHeight = 24; var letters = ‘0123456789abcdefghijklmnopqrstuvwxyz‘; var context = document.getElementById(‘canvas‘).getContext(‘2d‘); context.font = ‘16px 微软雅黑‘; context.textBaseline = ‘top‘; image.onload = function() { for (var i = 0; i < letters.length; i++) { var letter = letters[i]; // 绘制白色背景,与图片背景对应 context.fillStyle = ‘#fff‘; context.fillRect(0, 0, width, 18); // 绘制文字,以获取字型数据 context.fillStyle = ‘#000‘; context.fillText(letter, 0, 0); // 获取字符绘制宽度 var width = context.measureText(letter).width; stanData[letter] = { width : width, data : getBinary(context.getImageData(0, 0, width, 18).data) }; // 清空该区域以获取下个字符字型数据 context.clearRect(0, 0, width, 18); } context.fillStyle = ‘#000‘; context.fillText(‘512abcxyz‘, 0, 0); findLetter(0, 0, ‘‘); alert(result); }; var result = ‘‘; function findLetter(x, y, str) { console.log(x, y, str); if (result != ‘‘) return; var queue = []; for (var letter in stanData) { if (y > lineHeight * 3) { result = str; break; } // 边界 var width = stanData[letter].width; if (x + width > 440) { continue; } // 获取该矩形区域下的灰度化0-1数据 var data = getBinary(context.getImageData(x, y, width, 18).data); // 计算偏差 var deviation = 0, flag = true; for (var i = 0; i < data.length; i++) { if (data[i]) flag = false; if (data[i] != stanData[letter].data[i]) deviation++; } if (letter == ‘0‘) alert(deviation); // 如果已经到了行末,重置匹配坐标 // if (flag) { // findLetter(0, y + lineHeight, str + ‘\n‘); // break; // } // 如果偏差量与宽度的比值小于3,则纳入匹配队列中 // 这里也是算法中的关键点,怎样的偏差量可以纳入匹配队列中 // 刚开始是直接用绝对偏差量判断,当偏差量小于某个值的时候则匹配成功,但调试过程中发现不妥之处 // 字符字型较小的绝对偏差量自然也小,这样l,i等较小的字型特别容易匹配成功 // 因此使用偏差量与字型宽度的比值作为判断依据较为合理 console.log(letter, deviation, deviation / width); if (deviation / width < 3) { queue.push({ letter : letter, width : width, deviation : deviation }); } } // 如果匹配队列不为空 if (queue.length) { // 对队列进行排序,同样是根据偏差量与字符宽度的比例 queue.sort(compare); console.log(str, queue, queue.length); for (var i = 0; i < queue.length && !result; ++i) { var item = queue[i]; findLetter(x + item.width, y, str + item.letter); } } else { return; } } // 两个匹配到的字符的比较方法,用于排序 function compare(letter1, letter2) { return letter1.deviation / letter1.width - letter2.deviation / letter2.width; } // 图像数据的灰度化及0-1化 function getBinary(data) { var binaryData = []; for (var i = 0; i < data.length; i += 4) { binaryData[i / 4] = ((data[i] + data[i + 1] + data[i + 2]) / 3 < 200); } return binaryData; } </script> </body> </html>
3.3D云标签
<html> <head> <meta charset="UTF-8"> <style> .tag { display: block; position: absolute; text-decoration: none; } </style> </head> <body> <div class="content" style="width: 800px;height: 800px;margin: 50px auto; position: relative;"> <a class="tag" href="javascript:void(0)">A</a> <a class="tag" href="javascript:void(0)">B</a> <a class="tag" href="javascript:void(0)">C</a> <a class="tag" href="javascript:void(0)">D</a> <a class="tag" href="javascript:void(0)">E</a> <a class="tag" href="javascript:void(0)">A</a> <a class="tag" href="javascript:void(0)">B</a> <a class="tag" href="javascript:void(0)">C</a> <a class="tag" href="javascript:void(0)">D</a> <a class="tag" href="javascript:void(0)">E</a> </div> <script> var tagEle = document.querySelectorAll(".tag"), paper = document.querySelector(".content"); var R = 300, fallLength = 500; var tags = []; var angleX = Math.PI / 500, angleY = Math.PI / 500; var CX = paper.offsetWidth / 2, CY = paper.offsetHeight / 2, EX = paper.offsetLeft + document.body.scrollLeft + document.documentElement.scrollLeft, EY = paper.offsetTop + document.body.scrollTop + document.documentElement.scrollTop; function tag(ele, x, y, z) { this.ele = ele; this.x = x; this.y = y; this.z = z; this.print = function() { var scale = fallLength / (fallLength - this.z); var alpha = (this.z + R) / (2 * R); this.ele.style.fontSize = 80 * scale + "px"; this.ele.style.opacity = alpha + 0.5; this.ele.style.zIndex = parseInt(scale * 100); this.ele.style.left = this.x + CX - this.ele.offsetWidth / 2 + "px"; this.ele.style.top = this.y + CY - this.ele.offsetHeight / 2 + "px"; } } (function() { for (var i = 0; i < tagEle.length; i++) { var k = (2 * (i + 1) - 1) / tagEle.length - 1; var a = Math.acos(k); var b = a * Math.sqrt(tagEle.length * Math.PI); var x = R * Math.sin(a) * Math.cos(b); var y = R * Math.sin(a) * Math.sin(b); var z = R * Math.cos(a); var t = new tag(tagEle[i], x, y, z); tags.push(t); t.print(); } })(); setInterval(function() { var cosX = Math.cos(angleX); var sinX = Math.sin(angleX); var cosY = Math.cos(angleY); var sinY = Math.sin(angleY); tags.forEach(function(tag) { tag.y = tag.y * cosX - tag.z * sinX; tag.z = tag.z * cosX + tag.y * sinX; tag.x = tag.x * cosY - tag.z * sinY; tag.z = tag.z * cosY + tag.x * sinY; tag.print(); }) }, 20); paper.addEventListener("mousemove", function(event) { var x = event.clientX - EX - CX; var y = event.clientY - EY - CY; angleY = x * 0.0001; angleX = y * 0.0001; }); </script> </body> </html>
评论(0)