前端Canvas:让你的网站更具视觉冲击力

前端Canvas:让你的网站更具视觉冲击力

毒舌时刻

前端Canvas?这不是游戏开发才用的吗?

"Canvas性能差,我不用"——结果错过了丰富的视觉效果,
"Canvas太复杂了,我学不会"——结果只能用静态图片,
"我用CSS就够了,要Canvas干嘛"——结果无法实现复杂的动画效果。

醒醒吧,Canvas不是游戏开发的专利,前端也可以用它来创建丰富的视觉效果!

为什么你需要这个?

  • 丰富的视觉效果:创建动态图形、动画和游戏
  • 高性能:直接操作像素,性能优异
  • 交互性:支持鼠标、触摸等交互
  • 数据可视化:绘制图表、仪表盘等
  • 跨平台:在所有现代浏览器中运行

反面教材

// 反面教材:简单的Canvas绘制 function drawCircle() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // 绘制一个简单的圆形 ctx.beginPath(); ctx.arc(100, 100, 50, 0, Math.PI * 2); ctx.fillStyle = 'red'; ctx.fill(); ctx.stroke(); } // 反面教材:没有优化的动画 function animate() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); let x = 0; setInterval(() => { // 每次都清除整个画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 绘制移动的矩形 ctx.fillStyle = 'blue'; ctx.fillRect(x, 50, 50, 50); x += 1; if (x > canvas.width) { x = 0; } }, 16); } 

正确的做法

// 正确的做法:Canvas基础绘制 function basicDrawing() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // 设置画布尺寸 canvas.width = 800; canvas.height = 600; // 绘制矩形 ctx.fillStyle = 'blue'; ctx.fillRect(50, 50, 100, 100); // 绘制圆形 ctx.beginPath(); ctx.arc(250, 100, 50, 0, Math.PI * 2); ctx.fillStyle = 'red'; ctx.fill(); // 绘制路径 ctx.beginPath(); ctx.moveTo(350, 50); ctx.lineTo(450, 150); ctx.lineTo(350, 150); ctx.closePath(); ctx.strokeStyle = 'green'; ctx.lineWidth = 2; ctx.stroke(); // 绘制文本 ctx.font = '24px Arial'; ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.fillText('Canvas绘制示例', canvas.width / 2, 30); } // 正确的做法:Canvas动画 function canvasAnimation() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 800; canvas.height = 600; let x = 0; let y = canvas.height / 2; let dx = 2; let dy = 2; const radius = 20; function animate() { // 清除画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 绘制移动的圆形 ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2); ctx.fillStyle = 'purple'; ctx.fill(); // 边界检测 if (x + radius > canvas.width || x - radius < 0) { dx = -dx; } if (y + radius > canvas.height || y - radius < 0) { dy = -dy; } // 更新位置 x += dx; y += dy; // 使用requestAnimationFrame requestAnimationFrame(animate); } animate(); } // 正确的做法:Canvas交互 function canvasInteraction() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 800; canvas.height = 600; let isDrawing = false; let lastX = 0; let lastY = 0; // 鼠标按下事件 canvas.addEventListener('mousedown', (e) => { isDrawing = true; [lastX, lastY] = [e.offsetX, e.offsetY]; }); // 鼠标移动事件 canvas.addEventListener('mousemove', (e) => { if (!isDrawing) return; ctx.beginPath(); ctx.moveTo(lastX, lastY); ctx.lineTo(e.offsetX, e.offsetY); ctx.strokeStyle = 'black'; ctx.lineWidth = 2; ctx.stroke(); [lastX, lastY] = [e.offsetX, e.offsetY]; }); // 鼠标释放事件 canvas.addEventListener('mouseup', () => { isDrawing = false; }); // 鼠标离开事件 canvas.addEventListener('mouseout', () => { isDrawing = false; }); } // 正确的做法:Canvas数据可视化 function canvasChart() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 800; canvas.height = 600; // 数据 const data = [12, 19, 3, 5, 2, 3, 7, 11, 15, 18, 10, 6]; const labels = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']; // 绘制坐标系 const padding = 50; const chartWidth = canvas.width - padding * 2; const chartHeight = canvas.height - padding * 2; // X轴 ctx.beginPath(); ctx.moveTo(padding, canvas.height - padding); ctx.lineTo(canvas.width - padding, canvas.height - padding); ctx.stroke(); // Y轴 ctx.beginPath(); ctx.moveTo(padding, padding); ctx.lineTo(padding, canvas.height - padding); ctx.stroke(); // 绘制数据 const maxValue = Math.max(...data); const barWidth = chartWidth / data.length; data.forEach((value, index) => { const barHeight = (value / maxValue) * chartHeight; const x = padding + index * barWidth; const y = canvas.height - padding - barHeight; // 绘制柱子 ctx.fillStyle = 'rgba(54, 162, 235, 0.6)'; ctx.fillRect(x + 5, y, barWidth - 10, barHeight); // 绘制标签 ctx.font = '12px Arial'; ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.fillText(labels[index], x + barWidth / 2, canvas.height - padding + 15); }); // 绘制标题 ctx.font = '20px Arial'; ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.fillText('月度销售数据', canvas.width / 2, padding / 2); } // 正确的做法:Canvas图像处理 function canvasImageProcessing() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 800; canvas.height = 600; // 加载图像 const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = () => { // 绘制原始图像 ctx.drawImage(img, 0, 0, 400, 300); // 获取图像数据 const imageData = ctx.getImageData(0, 0, 400, 300); const data = imageData.data; // 处理图像(灰度) for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; const gray = (r + g + b) / 3; data[i] = gray; data[i + 1] = gray; data[i + 2] = gray; } // 绘制处理后的图像 ctx.putImageData(imageData, 400, 0); }; img.src = 'https://picsum.photos/800/600'; } 

毒舌点评

看看,这才叫前端Canvas!不是简单地绘制几个图形,而是创建丰富的视觉效果、动画和交互。

记住,Canvas是一个强大的工具,它可以让你创建从简单的图表到复杂的游戏等各种视觉效果。合理使用Canvas,可以让你的网站更具视觉冲击力。

所以,别再觉得Canvas复杂了,它是前端视觉效果的重要工具!

总结

  • 基础绘制:矩形、圆形、路径、文本等
  • 动画效果:使用requestAnimationFrame实现流畅动画
  • 交互操作:鼠标、触摸等事件处理
  • 数据可视化:绘制图表、仪表盘等
  • 图像处理:像素级操作,实现滤镜效果
  • 性能优化:合理使用缓存、避免频繁重绘
  • 响应式:根据容器大小调整画布尺寸
  • 工具库:使用Chart.js、Fabric.js等库简化开发

前端Canvas,让你的网站更具视觉冲击力!

Read more

F076 中医中药知识智能问答与图谱构建研究系统 Vue+Flask+Neo4j

F076 中医中药知识智能问答与图谱构建研究系统 Vue+Flask+Neo4j

文章结尾部分有ZEEKLOG官方提供的学长 联系方式名片 关注B站,私信获取! 麦麦大数据 编号: F076 视频 <<待上传>> 1 系统简介 系统简介:本系统是一个基于Vue+Flask+Neo4j+MySQL构建的《中医中药知识智能问答与图谱构建研究系统》。其核心围绕中医证型、中药信息的数字化管理、智能问答及知识图谱的构建与多维度可视化分析能力展开。 本系统主要面向用户提供中医证型查询、中药推荐、病症知识智能问答等功能,同时面向管理员提供数据分析、用户管理、基础数据维护等系统级管理功能。其关键技术栈涵盖前后端分离架构、图数据库Neo4j、传统关系型数据库MySQL,结合多种文本挖掘算法(如TF-IDF、TextRank、YAKE)完成对数据内容的智能分析。 主要功能模块包括:用户登录与注册、中医证型管理、中药信息展示、知识图谱可视化、智能问答、病症知识推荐、用户画像分析、系统数据管理、个人信息设置等。 2 功能设计

如何轻松分析大疆无人机信号?DJI DroneID 信号解析工具全指南

如何轻松分析大疆无人机信号?DJI DroneID 信号解析工具全指南 🛸 【免费下载链接】dji_droneid 项目地址: https://gitcode.com/gh_mirrors/dj/dji_droneid DJI DroneID 信号分析项目(dji_droneid)是一个开源工具集,专为无人机爱好者和研究人员设计,通过软件定义无线电(SDR)技术捕获、解码和分析大疆无人机发射的DroneID信号。该项目提供完整的信号处理流程,从原始IQ数据捕获到最终数据帧解析,支持Octave和MATLAB环境运行,帮助用户深入理解无人机通信机制。 📌 项目核心功能与技术架构 🔍 信号捕获与处理全流程 项目实现了从射频信号到数据帧的完整解析链路,主要包括: * 原始信号采集:支持32位浮点IQ数据文件输入(需配合SDR设备录制) * ZC序列检测:通过归一化互相关算法定位信号中的Zadoff-Chu序列 * 频率校正:自动检测并补偿信号中的频率偏移 * OFDM符号提取:精准提取9个OFDM符号(含2个ZC序列符号) * 相位校正与均衡:解决无线信道引入的

低代码集成:将PDF-Extract-Kit-1.0接入Power Platform的完整教程

低代码集成:将PDF-Extract-Kit-1.0接入Power Platform的完整教程 你是不是也遇到过这样的情况:公司里每天都有大量PDF格式的合同、发票、报告需要处理,手动复制粘贴不仅费时费力,还容易出错?而开发一个完整的自动化系统又太复杂,API调用、身份验证、数据解析……光是想想就头大。 别担心,今天我要分享的这个方法,完全不需要写一行后端代码,就能把强大的AI驱动PDF解析能力——PDF-Extract-Kit-1.0,轻松集成到你的Power Apps应用中。哪怕你是零编程基础的业务人员,也能在30分钟内完成整个流程。 PDF-Extract-Kit-1.0 是目前开源社区中表现最出色的PDF内容提取工具之一。它不仅能精准识别文本、表格、图像和公式,还能理解文档的布局结构,即便是扫描件或模糊文件也能保持高准确率。更重要的是,它的模型已经预置在ZEEKLOG星图镜像广场中,支持一键部署为HTTP服务,这为我们通过Power Automate调用提供了极大便利。 本文将带你从零开始,一步步实现: * 如何快速部署 PDF-Extract-Kit-1.0 镜像

OpenClaw基础-3-telegram机器人配置与加入群聊

OpenClaw基础-3-telegram机器人配置与加入群聊 💡 大家好,我是可夫小子,《小白玩转ChatGPT》专栏作者,关注AI编程、AI自动化和自媒体。 Openclaw的优势是接入各种聊天工作,在前面的文章里,已经介绍了如何接入飞书。但之前我也提到了,飞书的最大的问题是请求多的限制,以及无法在非认证企业账号下面组建群聊。但这些限制另一个聊天工具可以打破,那就是Telegram,今天就跟大家分享一下,如果在OpenClaw里面接入Telegram。 第一步:Openclaw端配置 通过命令openclaw config,local→channels→telegrams 这里等待输入API Token,接下来我们去Telegram里面获取 第二步:Telegram端配置 1. 1. 在聊天窗口找到BotFather,打开对话与他私聊 2. 3. 然后再输入一个机器人,再输入一个账号名username,这里面要求以Bot或者Bot结尾,这个是全网的id,要 2. /newbot 来创建一个机器人,输入一个名字name