娄底网站建设工作室阿里云虚拟主机和云服务器的区别

张小明 2026/3/13 2:49:15
娄底网站建设工作室,阿里云虚拟主机和云服务器的区别,白酒网站源码,大量word发布wordpress#x1f4c5; 我们继续 50 个小项目挑战#xff01;—— DrawingApp 组件 仓库地址#xff1a;https://gitee.com/hhm-hhm/50days50projects.git 构建一个简单的在线画板应用。用户可以自由绘制图形、调节画笔粗细、选择颜色#xff0c;并支持一键清空画布。 #x1f30… 我们继续 50 个小项目挑战—— DrawingApp 组件仓库地址https://gitee.com/hhm-hhm/50days50projects.git构建一个简单的在线画板应用。用户可以自由绘制图形、调节画笔粗细、选择颜色并支持一键清空画布。 组件目标创建一个固定尺寸的画布区域支持鼠标点击拖动进行绘画提供按钮控制画笔粗细 / -使用原生input typecolor选择画笔颜色提供“清空”按钮重置画布内容使用 TailwindCSS 快速构建现代 UI 界面 DrawingApp.tsx组件实现import React, { useRef, useEffect, useState } from react const DrawingApp: React.FC () { // Refs const canvasRef useRefHTMLCanvasElement(null) const isDrawingRef useRef(false) // 使用 ref 避免 draw 闭包问题 const lastXRef useRef(0) const lastYRef useRef(0) const ctxRef useRefCanvasRenderingContext2D | null(null) // State const [brushSize, setBrushSize] useStatenumber(5) const [brushColor, setBrushColor] useStatestring(#000000) // 初始化画布 useEffect(() { const canvas canvasRef.current if (!canvas) return // 设置画布尺寸为显示尺寸避免模糊 const dpr window.devicePixelRatio || 1 const rect canvas.getBoundingClientRect() canvas.width rect.width * dpr canvas.height rect.height * dpr const ctx canvas.getContext(2d) if (!ctx) return // 缩放上下文以适配高清屏 ctx.scale(dpr, dpr) ctx.lineCap round ctx.lineJoin round ctxRef.current ctx }, []) // 开始绘制仅左键 const startDrawing (e: React.MouseEventHTMLCanvasElement) { if (e.button ! 0) return // 只响应左键 const canvas canvasRef.current if (!canvas) return const rect canvas.getBoundingClientRect() const x e.clientX - rect.left const y e.clientY - rect.top lastXRef.current x lastYRef.current y isDrawingRef.current true } // 绘制中 const draw (e: React.MouseEventHTMLCanvasElement) { if (!isDrawingRef.current || !ctxRef.current) return const canvas canvasRef.current if (!canvas) return const rect canvas.getBoundingClientRect() const x e.clientX - rect.left const y e.clientY - rect.top const ctx ctxRef.current ctx.beginPath() ctx.moveTo(lastXRef.current, lastYRef.current) ctx.lineTo(x, y) ctx.strokeStyle brushColor ctx.lineWidth brushSize ctx.stroke() lastXRef.current x lastYRef.current y } // 停止绘制 const stopDrawing () { isDrawingRef.current false } // 控制画笔大小 const increaseBrushSize () { setBrushSize((prev) Math.min(prev 1, 50)) } const decreaseBrushSize () { setBrushSize((prev) Math.max(prev - 1, 1)) } // 清空画布 const clearCanvas () { const canvas canvasRef.current const ctx ctxRef.current if (!canvas || !ctx) return ctx.clearRect( 0, 0, canvas.width / (window.devicePixelRatio || 1), canvas.height / (window.devicePixelRatio || 1) ) } return ( div classNameflex min-h-screen items-center justify-center bg-gray-900 div classNameflex flex-col items-center {/* 画板区域 */} canvas ref{canvasRef} classNameaspect-square w-[800px] border-2 border-gray-300 bg-white onMouseDown{startDrawing} onMouseMove{draw} onMouseUp{stopDrawing} onMouseLeave{stopDrawing} onContextMenu{(e) e.preventDefault()} // 禁用右键菜单 / {/* ️ 工具栏 */} div classNamemt-4 flex w-[800px] items-center justify-between rounded-lg bg-gray-800 p-3 {/* 粗细调节 */} div classNameflex items-center button onClick{decreaseBrushSize} classNamerounded p-2 text-white hover:bg-gray-700 disabled{brushSize 1} - /button span classNamemx-3 text-white{brushSize}/span button onClick{increaseBrushSize} classNamerounded p-2 text-white hover:bg-gray-700 disabled{brushSize 50} /button /div {/* 颜色选择 */} input typecolor value{brushColor} onChange{(e) setBrushColor(e.target.value)} classNameh-10 w-10 cursor-pointer appearance-none rounded border-0 bg-transparent / {/* 清空画布 */} button onClick{clearCanvas} classNamerounded bg-red-600 p-2 text-white hover:bg-red-700 清空 /button /div /div div classNamefixed right-20 bottom-5 text-2xl text-red-500CSDNHao_Harrision/div /div ) } export default DrawingApp 关键技术说明1.使用useRef管理可变状态isDrawing,lastX,lastY使用ref而非state避免draw函数因闭包捕获旧值。ctx也用ref缓存避免重复获取。2.高 DPI 屏幕适配防模糊获取devicePixelRatio并放大 canvas 尺寸同时缩放绘图上下文ctx.scale(dpr, dpr)清空时需除以dpr得到逻辑尺寸。3.坐标计算使用getBoundingClientRect()获取 canvas 位置clientX/Y - rect.left/top得到相对于 canvas 的坐标。4.事件处理onMouseDown/onMouseMove等使用 React 事件系统onContextMenu阻止默认右键菜单。5.无障碍与 UX按钮添加disabled状态当画笔已达最小/最大颜色选择器移除浏览器默认样式appearance-noneborder-0。 可选增强建议功能实现方式移动端支持添加onTouchStart/onTouchMove等事件撤销功能保存 canvas 快照到栈中导出图片使用canvas.toDataURL()自定义背景在clearCanvas中填充背景色或图案 TailwindCSS 样式重点讲解 TailwindCSS 样式说明类名作用min-h-screen设置最小高度为视口高度items-center,justify-centerFlexbox 居中对齐布局bg-gray-900设置深色背景aspect-square保持画布为正方形比例w-[800px]固定宽度为 800pxborder-2,border-gray-300边框样式bg-white画布背景色rounded-lg,p-3工具栏圆角与内边距hover:bg-gray-700按钮悬停变色ext-white白色文字cursor-pointer鼠标悬停变为手型h-10,w-10设置颜色选择器大小 路由组件 常量定义router/index.tsx中children数组中添加子路由{ path: /, element: App /, children: [ ... { path: /DrawingApp, lazy: () import(/projects/DrawingApp.tsx).then((mod) ({ Component: mod.default, })), }, ], },constants/index.tsx 添加组件预览常量import demo22Img from /assets/pic-demo/demo-22.png 省略部分.... export const projectList: ProjectItem[] [ 省略部分.... { id: 22, title: DrawingApp, image: demo22Img, link: DrawingApp, }, 小结你可以进一步扩展此组件的功能例如✅ 支持保存画布内容为图片canvas.toDataURL()✅ 添加撤销/重做功能记录历史快照✅ 支持触控设备如 iPad 或触摸屏✅ 封装为独立组件支持 props 传入默认颜色或大小 明日预告 我们将完成KineticLoader组件一个很有意思的旋转加载动画。原文链接https://blog.csdn.net/qq_44808710/article/details/149150719每天造一个轮子码力暴涨不是梦
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

平泉县住房和城乡建设局网站公司网站备案需要哪些

在信息获取日益重要的今天,付费墙已成为阻碍知识传播的主要障碍。Bypass Paywalls Clean作为一款专业级浏览器扩展,通过创新的技术手段帮助用户突破这一限制,实现全球优质内容的无障碍访问。本指南将深入解析其工作原理、安装配置及最佳实践。…

张小明 2026/3/5 3:02:36 网站建设

郴州买房网站莆田网站建设建站系统

5种高效解锁付费内容的实用技术方案深度解析 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在信息爆炸的时代,优质内容往往被付费墙层层包裹,让求知者望而却步…

张小明 2026/3/5 3:03:09 网站建设

做网站需要懂什么技术网站运营与管理的内容有哪些

一、为什么需要“多模态 RAG”? 传统 RAG 痛点多模态 RAG 价值只能检索/生成文本图像、音频、视频、3D、代码、表格全支持幻觉严重外部知识实时注入,无需重新训练单模态检索 → 单模态输出任意模态组合输入 → 任意模态组合输出MM-RAG数学定义 随着 GP…

张小明 2026/3/5 3:02:41 网站建设

新农村建设官方网站网站后期维护费用多少

【YOLO-Ultralytics】 【核心引擎】【v8.3.235版本】 模型预测器基类代码predictor.py解析 文章目录【YOLO-Ultralytics】 【核心引擎】【v8.3.235版本】 模型预测器基类代码predictor.py解析前言YOLO 预测功能全解析输入源(source 参数)说明模型格式&am…

张小明 2026/3/5 3:02:40 网站建设

网站的色彩搭配网站上全景云台怎么做的

EmotiVoice 结合大模型 Token 服务实现按需语音生成 在智能语音交互日益普及的今天,用户早已不满足于“能说话”的机器。他们期待的是有温度、有情绪、甚至能唤起共鸣的声音——就像一位熟悉的朋友,在恰当的时机用合适的语气说出恰如其分的话。 然而&…

张小明 2026/3/12 13:41:20 网站建设