canvas基础简单易懂教程(完结,多图)

Python微信订餐小程序课程视频

https://blog.csdn.net/m0_56069948/article/details/122285951

Python实战量化交易理财系统

https://blog.csdn.net/m0_56069948/article/details/122285941
目录* Canvas学习
+ 一、 Canvas概述
- 1.1 Hello world
- 1.2 Canvas的像素化
- 1.3 Canvas的动画思想
- 1.4 面向对象思维实现canvas动画
+ 二、Canvas的绘制功能
- 2.1 绘制矩形
- 2.2 绘制路径
- 2.3 绘制圆弧
- 2.4 炫彩小球
- 2.5 透明度
- 2.6 小球连线
- 2.7 线型
* lineWidth
* lineCap
* lineJoin
* setLineDash
* lineDashOffset
- 2.8 文本
- 2.9 渐变 Gradients
- 2.10 阴影
+ 三、使用图片
+ 四、资源管理器
+ 4.1 获取对象中属性的长度
+ 4.2 管理器的实现
+ 五、变形
- 5.1 移动translate
- 5.2 旋转 rotate
- 5.3 缩放 scale
- 5.4 变形 transform
- 5.5 滚动的车轮案例
+ 六、合成与裁剪
- 6.1 globalCompositeOperation
- 6.2 裁剪路径
- 6.3 刮刮乐案例
+ 七、总结

Canvas学习

canvas 读音 /ˈkænvəs/, 即kæn və s(看我死).

学习的目的主要是为了网状关系拓扑图形的绘制.

推荐文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial

一、 Canvas概述

canvas是用来绘制图形的.它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

长久以来, web上的动画都是Flash. 比如动画广告\ 游戏等等, 基本都是Flash 实现的. Flash目前都被禁用了, 而且漏洞很多, 重量很大, 需要安装Adobe Flash Player, 而且也会卡顿和不流畅等等.

canvas是HTML5提出的新标签,彻底颠覆了Flash的主导地位。无论是广告、游戏都可以使用canvas实现。

Canvas 是一个轻量级的画布, 我们使用Canvas进行JS的编程,不需要增加额外的组件,性能也很好,不卡顿,在手机中也很流畅。

1.1 Hello world

我们可以在页面中设置一个canvas标签



|  |  |
|  |  当前的浏览器版本不支持,请升级浏览器 |
|  | canvas> |


canvas的标签属性只有两个,width和height,表示的是canvas画布的宽度和高度,不要用css来设置,而是用属性来设置,画布会失真变形。

标签的innerContent是用来提示低版本浏览器(IE6、7、8)并不能正常使用canvas,高版本的浏览器是看不到canvas标签内部的文字的。

canvas基础简单易懂教程(完结,多图)_第1张图片



|  | // 得到canvas的画布 |
|  | const myCanvas:HTMLCanvasElement = document.getElementById("main\_canvas") as HTMLCanvasElement// 返回某种类型的HTMLElement |
|  |  |
|  | // 得到画布的上下文,上下文有两个,2d的上下文和3d的上下文 |
|  | // 所有的图像绘制都是通过ctx属性或者是方法进行设置的,和canvas标签没有关系了 |
|  | const ctx = myCanvas.getContext("2d") |
|  | if(ctx !== null) { |
|  | // 设置颜色 |
|  |  ctx.fillStyle = 'green' |
|  | // 绘制矩形 |
|  |  ctx.fillRect(100, 100, 200, 50)  |
|  | } |


canvas基础简单易懂教程(完结,多图)_第2张图片

通过上面的代码我们发下canvas本质上就是利用代码在浏览器的页面上进行画画,比如上面的代码fillRect就代表在页面中绘制矩形,一共四个属性,前两个100,100代表(x, y), 即填充起始位置,200代表宽,50代表高,单位都是px。

1.2 Canvas的像素化

我们用canvas绘制了一个图形,一旦绘制成功了,canvas就像素化了他们。canvas没有能力,从画布上再次得到这个图形,也就是我们没有能力去修改已经在画布上的内容,这个就是canvas比较轻量的原因,Flash重的原因之一就有它可以通过对应的api得到已经上“画布”的内容然后再次绘制

如果我们想要这个canvas图形移动,必须按照:清屏——更新——渲染的逻辑进行编程。总之,就是重新再画一次

1.3 Canvas的动画思想

要使用面向对象的思想来创建动画。

canvas上画布的元素,就被像素化了,所以不能通过style.left方法进行修改,而且必须要重新绘制。



|  | // 得到画布 |
|  | const myCanvas:HTMLCanvasElement = document.getElementById("main\_canvas") as HTMLCanvasElement |
|  |  |
|  | // 获取上下文 |
|  | const ctx = myCanvas.getContext("2d") |
|  |  |
|  | if(ctx !== null) { |
|  | // 设置颜色 |
|  |  ctx.fillStyle = "blue" |
|  | // 初始信号量 |
|  | let left:number = -200 |
|  | // 动画过程 |
|  | setInterval(() => { |
|  | // 清除画布,0,0代表从什么位置开始,600,600代表清除的宽度和高度 |
|  |  ctx.clearRect(0,0,600,600) |
|  | // 更新信号量 |
|  |  left++ |
|  | // 如果已经走出画布,则更新信号量为初始位置 |
|  | if(left > 600) { |
|  |  left = -200 |
|  |  } |
|  |  ctx.fillRect(left, 100, 200, 200) |
|  |  },10) |
|  | } |


canvas基础简单易懂教程(完结,多图)_第3张图片

实际上,动画的生成就是相关静态画面连续播放,这个就是动画的过程。我们把每一次绘制的静态话面叫做一帧,时间的间隔(定时器的间隔)就是表示的是帧的间隔。

1.4 面向对象思维实现canvas动画

因为canvas不能得到已经上屏的对象,所以我们要维持对象的状态。在canvas动画重,我们都是用面向对象来进行编程,因为我们可以使用面向对象的方式来维持canvas需要的属性和状态;



|  | // 得到画布 |
|  | const myCanvas:HTMLCanvasElement = document.getElementById("main\_canvas") as HTMLCanvasElement |
|  |  |
|  | // 获取上下文 |
|  | const ctx = myCanvas.getContext("2d") |
|  |  |
|  | class Rect { |
|  | // 维护状态 |
|  | constructor( |
|  | public x: number, |
|  | public y: number,  |
|  | public w: number,  |
|  | public h: number,  |
|  | public color: string |
|  |  ) {  |
|  |  } |
|  | // 更新的方法 |
|  | update() { |
|  | this.x++ |
|  | if(this.x > 600) { |
|  | this.x = -200 |
|  |  } |
|  |  } |
|  | // 渲染 |
|  | render(ctx: CanvasRenderingContext2D) { |
|  | // 设置颜色 |
|  |  ctx.fillStyle = this.color |
|  | // 渲染 |
|  |  ctx.fillRect(this.x, this.y, this.w, this.h) |
|  |  } |
|  | } |
|  |  |
|  | // 实例化 |
|  | let myRect1: Rect = new Rect(-100, 200, 100, 100, 'purple') |
|  | let myRect2: Rect = new Rect(-100, 400, 100, 100, 'pink') |
|  |  |
|  | // 动画过程 |
|  |  |
|  | // 更新的办法 |
|  | setInterval(() => { |
|  | // 清除画布,0,0代表从什么位置开始,600,600代表清除的宽度和高度 |
|  | if(ctx !== null) { |
|  | // 清屏 |
|  |  ctx.clearRect(0,0,600,600) |
|  | // 更新方法 |
|  |  myRect1.update() |
|  |  myRect2.update() |
|  | // 渲染方法 |
|  |  myRect1.render(ctx) |
|  |  myRect2.render(ctx) |
|  |  } |
|  | },10) |


canvas基础简单易懂教程(完结,多图)_第4张图片

动画过程在主定时器重,每一帧都会调用实例的更新和渲染方法。

二、Canvas的绘制功能

2.1 绘制矩形

填充一个矩形:



|  | if(ctx !== null) { |
|  | // 设置颜色 |
|  |  ctx.fillStyle = 'green' |
|  | // 填充矩形 |
|  |  ctx.fillRect(100, 100, 300, 50) |
|  | } |


参数含义:分别代表填充坐标x、填充坐标y、矩形的高度和宽度。

绘制矩形边框,和填充不同的是绘制使用的是strokeRect, 和strokeStyle实现的



|  | if (ctx !== null) { |
|  | // 设置颜色 |
|  |  ctx.strokeStyle = 'red' |
|  | // 绘制矩形 |
|  |  ctx.strokeRect(300, 100, 100, 100) |
|  | } |


参数含义:分别代表绘制坐标x、绘制坐标y、矩形的高度和宽度。

canvas基础简单易懂教程(完结,多图)_第5张图片

清除画布,使用clearRect



|  | // 擦除画布内容 |
|  | btn3.onclick = () => { |
|  | if (ctx !== null) { |
|  |  ctx.clearRect(0, 0, 600, 600) |
|  |  } |
|  | } |


参数含义:分别代表擦除坐标x、擦除坐标y、擦除的高度和擦除的宽度。

2.2 绘制路径

绘制路径的作用是为了设置一个不规则的多边形状态

路径都是闭合的,使用路径进行绘制的时候需要既定的步骤:

  1. 需要设置路径的起点
  2. 使用绘制命令画出路径
  3. 封闭路径
  4. 填充或者绘制已经封闭路径的形状


|  | // 创建一个路径 |
|  | ctx.beginPath() |
|  | // 1. 移动绘制点 |
|  | ctx.moveTo(100, 100) |
|  | // 2. 描述行进路径 |
|  | ctx.lineTo(200, 200) |
|  | ctx.lineTo(400, 180) |
|  | ctx.lineTo(380, 50) |
|  | // 3. 封闭路径 |
|  | ctx.closePath(); |
|  |  |
|  | // 4. 绘制这个不规则的图形 |
|  | ctx.strokeStyle = 'red' |
|  | ctx.stroke() |
|  | ctx.fillStyle = 'orange' |
|  | ctx.fill() |


canvas基础简单易懂教程(完结,多图)_第6张图片

总结我们要绘制一个图形,要按照顺序

  1. 开始路径ctx.beginPath()
  2. 移动绘制点ctx.moveTo(x, y)
  3. 描述绘制路径ctx.lineTo(x, y)
  4. 多次描述绘制路径ctx.lineTo(x, y)
  5. 闭合路径ctx.closePath()
  6. 描边ctx.stroke()
  7. 填充ctx.fill()

此时我们发现之前我们在学习绘制矩形的时候使用的是fillRectstrokeRect,但是实际上fillstroke也是具有绘制填充功能的

stroke(): 通过线条来绘制图形轮廓。

fill(): 通过填充路径的内容区域生成实心的图形。

我们在绘制路径的时候选择不关闭路径(closePath),这个时候会实现自封闭现象(只针对fill,stroke不生效)

canvas基础简单易懂教程(完结,多图)_第7张图片

2.3 绘制圆弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)

画一个以(x, y)为圆心的以radius为半径的圆弧(圆), 从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针false, true为逆时针)来生成。



|  | // 创建一个路径 |
|  | ctx.beginPath() |
|  | // 移动绘制点 |
|  | // ctx.arc(200, 200, 100, 0, 2 * Math.PI, false) |
|  | ctx.arc(200, 200, 100, 0, 2 * 3.14, false) |
|  |  |
|  | ctx.stroke() |


圆弧也是绘制路径的一种,也需要beginPath和stroke.

canvas基础简单易懂教程(完结,多图)_第8张图片

参数的含义:200, 200代表的是起始x,y坐标,100代表的是圆心半径,0和1代表的是开始和结束位置,单位如果是数字,代表的是一个圆弧的弧度(一个圆的弧度是Math.PI * 2, 约等于7个弧度),所以在顺时针的情况下,如果如果两个参数的差为7,则代表绘制一个圆。

2.4 炫彩小球



|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById("main\_canvas") as HTMLCanvasElement |
|  |  |
|  | // 获取上下文 |
|  | const ctx = myCanvas.getContext("2d") |
|  |  |
|  | class Ball { |
|  | color: string // 小球的颜色 |
|  | r: number // 小球的半径 |
|  | dx: number // 小球在x轴的运动速度/帧 |
|  | dy: number // 小球在y轴的运动速度/帧 |
|  | constructor(public x: number, public y: number) { |
|  | // 设置随机颜色 |
|  | this.color = this.getRandomColor() |
|  | // 设置随机半径[1, 101) |
|  | this.r = Math.floor(Math.random() * 100 + 1) |
|  | // 设置x轴, y轴的运动速度(-5, 5) |
|  | this.dx = Math.floor(Math.random() * 10) - 5 |
|  | this.dy = Math.floor(Math.random() * 10) - 5 |
|  |  } |
|  | // 随机颜色,最后返回的是类似'#3fe432' |
|  | getRandomColor(): string { |
|  | let allType = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f" |
|  | let allTypeArr = allType.split(',') |
|  | let color = '#' |
|  | for (let i = 0; i < 6; i++) { |
|  | let random = Math.floor(Math.random() * allTypeArr.length) |
|  |  color += allTypeArr[random] |
|  |  } |
|  | return color |
|  |  } |
|  |  |
|  | // 渲染小球 |
|  | render(): void { |
|  | if(ctx !== null) { |
|  |  ctx.beginPath() |
|  |  ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false) |
|  |  ctx.fillStyle=this.color |
|  |  ctx.fill() |
|  |  } |
|  |  } |
|  |  |
|  | // 更新小球 |
|  | update(): void { |
|  | // 小球的运动 |
|  | this.x += this.dx |
|  | this.y += this.dy |
|  | this.r -= 0.5 |
|  | // 如果小球的半径小于0了,从数组中删除 |
|  | if(this.r <= 0) { |
|  | this.remove() |
|  |  } |
|  |  } |
|  |  |
|  | // 移除小球 |
|  | remove(): void { |
|  | for(let i = 0; i < ballArr.length; i++) { |
|  | if(ballArr[i] === this) { |
|  |  ballArr.splice(i, 1) |
|  |  } |
|  |  } |
|  |  } |
|  | } |
|  | // 维护小球的数组 |
|  | let ballArr: Ball[] = [] |
|  |  |
|  | // canvas设置鼠标监听 |
|  | myCanvas.addEventListener("mousemove", (event)=> { |
|  |  ballArr.push(new Ball(event.offsetX, event.offsetY)) |
|  | }) |
|  |  |
|  |  |
|  | // 定时器进行动画渲染和更新 |
|  | setInterval(function() { |
|  | // 动画的逻辑,清屏-更新-渲染 |
|  | if(ctx !== null) { |
|  |  ctx.clearRect(0, 0, myCanvas.width, myCanvas.height) |
|  |  } |
|  | for(let i = 0; i < ballArr.length; i++) { |
|  | // 小球的更新和渲染 |
|  |  ballArr[i].update() |
|  | if(ballArr[i]) { |
|  |  ballArr[i].render() |
|  |  } |
|  |  |
|  |  } |
|  | // 60 帧 |
|  | }, 1000 / 60) |


2.5 透明度

透明度的值是0到1之间: (1是完全不透明,0是完全透明)



|  | ctx.globalAlpha = 1 |


2.6 小球连线



|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById("mycanvas") as HTMLCanvasElement |
|  |  |
|  | // 获取上下文 |
|  | const ctx = myCanvas.getContext("2d") |
|  |  |
|  | // 设置画布的尺寸 |
|  | myCanvas.width = document.documentElement.clientWidth - 30 |
|  | myCanvas.height = document.documentElement.clientHeight - 30 |
|  |  |
|  | class Ball { |
|  | x: number = Math.floor(Math.random() * myCanvas.width) |
|  | y: number = Math.floor(Math.random() * myCanvas.height) |
|  | r: number = 10 |
|  | color: string = 'gray' |
|  | dx: number = Math.floor(Math.random() * 10) - 5 |
|  | dy: number = Math.floor(Math.random() * 10) - 5 |
|  | constructor() { |
|  |  ballArr.push(this) |
|  |  } |
|  |  |
|  | // 小球的渲染 |
|  | render() { |
|  | if(ctx !== null) { |
|  |  ctx.beginPath() |
|  | // 透明度 |
|  |  ctx.globalAlpha = 1 |
|  | // 画小球 |
|  |  ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false) |
|  |  ctx.fillStyle = this.color |
|  |  ctx.fill() |
|  |  } |
|  |  } |
|  | // 小球的更新 |
|  | update() { |
|  | // 更新x |
|  | this.x += this.dx |
|  | // 纠正x |
|  | if(this.x <= this.r) { |
|  | this.x = this.r |
|  |  } else if ( this.x >= myCanvas.width - this.r) { |
|  | this.x = myCanvas.width - this.r |
|  |  } |
|  | // 更新y |
|  | this.y += this.dy |
|  | // 纠正y |
|  | if(this.y <= this.r) { |
|  | this.y = this.r |
|  |  } else if ( this.y >= myCanvas.height - this.r) { |
|  | this.y = myCanvas.height - this.r |
|  |  } |
|  | // 碰壁返回 |
|  | if(this.x + this.r >= myCanvas.width || this.x - this.r <= 0) { |
|  | this.dx *= -1 |
|  |  } |
|  | if(this.y + this.r >= myCanvas.height || this.y - this.r <= 0) { |
|  | this.dy *= -1 |
|  |  } |
|  |  } |
|  |  |
|  | } |
|  |  |
|  | // 小球数组 |
|  | let ballArr: Ball[] = [] |
|  |  |
|  | // 创建20个小球 |
|  | for(let i = 0; i < 20; i++) { |
|  | new Ball() |
|  | } |
|  |  |
|  | // 定时器动画 |
|  | setInterval(() => { |
|  | // 清除画布 |
|  | if(ctx !== null) { |
|  |  ctx.clearRect(0, 0, myCanvas.width, myCanvas.height) |
|  |  } |
|  | // 小球渲染和更新 |
|  | for(let i = 0; i < ballArr.length; i++) { |
|  |  ballArr[i].render() |
|  |  ballArr[i].update() |
|  |  } |
|  | // 画线的逻辑 |
|  | if(ctx !== null) { |
|  | for(let i = 0; i < ballArr.length; i++) { |
|  | for(let j = i + 1; j < ballArr.length; j++) { |
|  | let distance = Math.sqrt(Math.pow((ballArr[i].x - ballArr[j].x), 2) + Math.pow((ballArr[i].y -ballArr[j].y), 2)) |
|  | if( distance <= 150) { |
|  |  ctx.strokeStyle = '#000' |
|  |  ctx.beginPath() |
|  | // 线的透明度,根据当前已经连线的小球的距离进行线的透明度设置 |
|  | // 距离越近透明度越大,距离越远透明度越小 |
|  |  ctx.globalAlpha = 1 - distance / 150 |
|  |  ctx.moveTo(ballArr[i].x, ballArr[i].y) |
|  |  ctx.lineTo(ballArr[j].x, ballArr[j].y) |
|  |  ctx.closePath() |
|  |  ctx.stroke() |
|  |  } |
|  |  } |
|  |  } |
|  |  } |
|  | }, 1000/60) |


2.7 线型

lineWidth

我们可以利用lineWidth设置线的粗细,属性值为number型,默认为1,没有单位



|  | ctx.lineWidth = 1.0 |


canvas基础简单易懂教程(完结,多图)_第9张图片

lineCap

我们可以使用lineCap指定如何绘制每一条线段末端的属性:"butt" | "round" | "square", 其中butt代表线段末端以方形结束,round表示线段末端以圆形结束,square线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域,默认是butt



|  | ctx.lineCap = "round"; |


canvas基础简单易懂教程(完结,多图)_第10张图片

canvas基础简单易懂教程(完结,多图)_第11张图片

该图是三种lineCapd的类型,从左到右依次为buttroundsquare

lineJoin

我们可以使用lineJoin来设置设置2个长度不为0的相连部分(线段,圆弧,曲线)如何连接在一起的属性(长度为0的变形部分,其指定的末端和控制点在同一位置,会被忽略):"bevel" | "round" | "miter"



|  | ctx.lineJoin = "bevel"; |


  • round表示通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。
  • bevel表示在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。
  • mitter表示通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

canvas基础简单易懂教程(完结,多图)_第12张图片

setLineDash

我们可以使用setLineDash方法在填充线时使用虚线模式。



|  | ctx.setLineDash(segments); |


  • segments是一个Array数组。一组描述交替绘制线段和间距(坐标空间单位)长度的数字。 如果数组元素的数量是奇数, 数组的元素会被复制并重复。例如, [5, 15, 25] 会变成 [5, 15, 25, 5, 15, 25]。数组内部是虚线的交替状态


|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById("mycanvas") as HTMLCanvasElement |
|  |  |
|  | // 获取上下文 |
|  | const ctx = myCanvas.getContext("2d") |
|  |  |
|  | // 画布的尺寸 |
|  | myCanvas.width = document.documentElement.clientWidth - 30 |
|  | myCanvas.height = document.documentElement.clientHeight - 30 |
|  |  |
|  | if(ctx !== null) { |
|  |  ctx.setLineDash([15, 15]); |
|  |  ctx.strokeRect(50,50, 90, 90) |
|  |  ctx.setLineDash([15,10,2,10]) |
|  |  ctx.strokeRect(200,50, 90, 90) |
|  | } |


canvas基础简单易懂教程(完结,多图)_第13张图片

lineDashOffset

我们可以使用lineDashOffset设置虚线偏移量的属性。设置的是起始偏移量,使线向左移动value



|  | ctx.lineDashOffset = value; |


  • value偏移量是float精度的数字。 初始值为 0.0

2.8 文本

我们可以在画布上绘制文字:



|  | ctx.font = "30px 微软雅黑" // 空格前为文字大小,空格后为字体类型 |
|  | // 第一个参数为文字内容,第二和第三个参数为文字绘制坐标, |
|  | // 第四个参数是可选参数,代表文字的最大宽度,如果字体宽度超过该值则压缩字体宽度 |
|  | ctx.fillText("你好,世界!", 100, 100)  |


canvas基础简单易懂教程(完结,多图)_第14张图片

我们可以使用textAlign来设置文本的对齐选项。可选的值包括:start, end, left, right or center。默认值是 start。该对齐是基于fillText方法的x的值。



|  | ctx.textAlign = "left" || "right" || "center" || "start" || "end"; |


  • left : 文本左对齐。
  • right: 文本右对齐。
  • center: 文本居中对齐。
  • start: 文本对齐界线开始的地方 (左对齐指本地从左向右,右对齐指本地从右向左)。
  • end: 文本对齐界线结束的地方 (左对齐指本地从左向右,右对齐指本地从右向左)。

2.9 渐变 Gradients

提供两种渐变方式,一种是线性渐变,一种是径向渐变。

  • 线性渐变:createLinearGradient 方法接受 4 个参数,表示图形渐变线的起点 (x1,y1) 与终点 (x2,y2),渐变将沿着这条线向两边渐变。


|  | ctx.createLinearGradient(x1, y1, x2, y2) |


addColorStop内部接收两个参数,第一个参数是当前渐变的位置(0~1之间的小数),第二个参数是颜色。



|  | let liner: CanvasGradient = ctx.createLinearGradient(0, 0, 100, 100) |
|  | liner.addColorStop(0, 'red') |
|  | liner.addColorStop(.5, 'blue') |
|  | liner.addColorStop(.8, 'yellow') |
|  | liner.addColorStop(1, 'green') |
|  | ctx.fillStyle = liner |
|  | ctx.fillRect(10, 10, 100,100) |


canvas基础简单易懂教程(完结,多图)_第15张图片

径向渐变:createRadialGradient方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的开始圆形,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的结束圆形。



|  | let radial: CanvasGradient = ctx.createRadialGradient(100, 100, 0, 100, 100, 100) |
|  | radial.addColorStop(0, 'red') |
|  | radial.addColorStop(1, 'purple') |
|  | ctx.fillStyle = radial |
|  | ctx.arc(100, 100, 100, 0, Math.PI *2, false) |
|  | ctx.fill( |


canvas基础简单易懂教程(完结,多图)_第16张图片

2.10 阴影

我们可以在画布中设置画布的阴影的状态:

  • shadowOffsetX: shadowOffsetXshadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0
  • shadowOffsetY: shadowOffsetXshadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0
  • shadowBlur: shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0
  • shadowColor: shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。


|  | ctx.shadowOffsetX = 1 // 阴影左右偏离的距离 |
|  | ctx.shadowOffsetY = 1 // 阴影上下偏离的距离 |
|  | ctx.shadowBlur = 1 // 模糊状态 |
|  | ctx.shadowColor = 'green' // 阴影颜色 |
|  | ctx.font ='30px 宋体' |
|  | ctx.fillText('你好,世界!', 100, 100) |


canvas基础简单易懂教程(完结,多图)_第17张图片

三、使用图片

canvs中使用drawImage来绘制图片,主要是把外部的图片导入进来,绘制到画布上。

图片的渲染过程:



|  | // 导入图片 |
|  | if(ctx !== null) { |
|  | // 第一步是创建一个image元素 |
|  | let image:HTMLImageElement = new Image() |
|  | // 用src设置图片的地址 |
|  |  image.src = "image/test1.png" |
|  | // 必须要在onload函数内绘制图片,否则不会渲染 |
|  |  image.onload = function() { |
|  |  ctx.drawImage(image, 100, 100) |
|  |  } |
|  | } |


canvas基础简单易懂教程(完结,多图)_第18张图片

如果我们在drawImage里设置的参数一共是两个(不包含第一个image参数),表示的是图片的加载位置。



|  | ctx.drawImage(image, 100, 100) |


canvas基础简单易懂教程(完结,多图)_第19张图片

如果drawImage有四个参数,分别表示图片的绘制位置和图片的宽高。(注意,此时图像会被拉伸)



|  | ctx.drawImage(image, 100, 100, 50, 50) |


canvas基础简单易懂教程(完结,多图)_第20张图片

还可以使用八个参数的drawImage, 前四个参数指的是你在图片中设置切片的宽度和高度,以及切片的位置,后四个参数指的是切片在画布上的位置和切片宽度高度



|  | // ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); |
|  | ctx.drawImage(image, 100, 300, 200, 200) |
|  | ctx.drawImage(image, 100, 100, 200, 200, 100, 100, 200, 200) |


  • sx: 需要绘制到目标上下文中的,image的矩形(裁剪)选择框的左上角 X 轴坐标。
  • sy: 需要绘制到目标上下文中的,image的矩形(裁剪)选择框的左上角 Y 轴坐标。
  • sWidth: 需要绘制到目标上下文中的,image的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的sxsy开始,到image的右下角结束。
  • sHeight: 需要绘制到目标上下文中的,image的矩形(裁剪)选择框的高度。
  • dx: image的左上角在目标canvas上 X 轴坐标。
  • dy: image的左上角在目标canvas上 Y 轴坐标。
  • dWidth: image在目标canvas上绘制的宽度。 允许对绘制的image进行缩放。 如果不说明, 在绘制时image宽度不会缩放。
  • dHeight: image在目标canvas上绘制的高度。 允许对绘制的image进行缩放。 如果不说明, 在绘制时image高度不会缩放。

canvas基础简单易懂教程(完结,多图)_第21张图片

canvas基础简单易懂教程(完结,多图)_第22张图片

四、资源管理器

canvas基础简单易懂教程(完结,多图)_第23张图片

我们在开发游戏的时候,有一些静态资源是需要请求回来的,否则如果直接开始,某些静态资源没有,会报错,或者空白,比如我们的游戏被禁锢,如果没有请求回来就直接开始,页面会有空白现象。

资源管理器就是当游戏需要资源全部加载完毕的时候,再开始游戏

我们现在主要是图片的资源,所以我们要在canvas渲染过程中进行图片的资源加载。

4.1 获取对象中属性的长度

有下面一个JSON(对象),此时我们想获取当前这个JSON属性数量



|  | this.imgURL = { |
|  | 'fengjing1':'./image/下载1.jpg', |
|  | 'fengjing2':'./image/下载2.jpg', |
|  | 'fengjing3':'./image/下载3.jpg', |
|  | 'fengjing4':'./image/下载4.jpg', |
|  | 'fengjing5':'./image/下载5.jpg', |
|  | } |


此时我们使用this.imgURL.length是得不到的,因为当前的this.imgURL.length指的是获取imgURL对象的length属性,而不是获取当前对象的属性个数,会返回undefined

正确答案是使用Object.keys()来获取当前的属性key列表,然后通过这个列表获取长度。



|  | Object.keys(this.imgURL).length |


4.2 管理器的实现



|  | interface StringOrImage { |
|  | // 定义了一个接口,该接口要求对象的属性是string或者是HTMLImageElement类型 |
|  |  [index: string]: string | HTMLImageElement |
|  | } |
|  |  |
|  | class Game { |
|  | dom: HTMLCanvasElement |
|  | ctx: CanvasRenderingContext2D | null |
|  | imgURL: StringOrImage |
|  | constructor() { |
|  | // 得到画布 |
|  | this.dom = document.getElementById("mycanvas") as HTMLCanvasElement |
|  | // 获取上下文 |
|  | this.ctx = this.dom.getContext("2d") |
|  | // 在属性中保存需要的图片地址 |
|  | this.imgURL = { |
|  | // 'fengjing1':'./image/下载1.jpg', |
|  | // 'fengjing2':'./image/下载2.jpg', |
|  | // 'fengjing3':'./image/下载3.jpg', |
|  | // 'fengjing4':'./image/下载4.jpg', |
|  | // 'fengjing5':'./image/下载5.jpg', |
|  | 'fengjing1':'https://gimg2.baidu.com/image\_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242332225H9-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651933471&t=34b40d339ce3bc4177afb393e7785575', |
|  | 'fengjing2':'https://gimg2.baidu.com/image\_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2014%2F0827%2Fc0c92bd51bb72e6d12d5b877dce338e8.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651933483&t=453f28e751e0d54d70a2e3393e57b423', |
|  | 'fengjing3':'https://gimg2.baidu.com/image\_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F032120114622%2F200321114622-4-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651933493&t=e9017fa69deb525312e214d2583a76d4', |
|  | 'fengjing4':'https://pic.rmb.bdstatic.com/1530971282b420d77bdfb6444d854f952fe31f0d1e.jpeg', |
|  | 'fengjing5':'https://gimg2.baidu.com/image\_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp01%2F1ZZQ214233446-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651933521&t=2cc050574824ec2761b539ab3a697522', |
|  |  } |
|  | // 获取资源图片的总数 |
|  | let imgCount = Object.keys(this.imgURL).length |
|  | // 计数器,记录的是加载完毕的数量 |
|  | let count = 0 |
|  | // 遍历imgURL对象获取每一个路径地址 |
|  | for(let key in this.imgURL) { |
|  | // 备份每一张图片的地址 |
|  | let src: string = this.imgURL[key] as string |
|  | // 创建一个图片 |
|  | this.imgURL[key] = new Image(); |
|  |  |
|  | // 判断图片是否加载完成,如果完成了,记数,如果加载完毕的数量和总数量相同了,则说明资源加载完毕 |
|  | // 第一种方法,将值提取出去做类型缩小 |
|  | let value = this.imgURL[key] |
|  | // 类型缩小成HTMLImageElement类型 |
|  | if(typeof value !== 'string') { |
|  |  value.src = src |
|  |  value.onload = () => { |
|  | // 增加计数器 |
|  |  count++ |
|  | if(this.ctx !== null) { |
|  | // 清屏 |
|  | this.ctx.clearRect(0, 0, 600, 600) |
|  | this.ctx.font = '16px Arial' |
|  | this.ctx.fillText("图片已经加载:" + count +" / " + imgCount, 50, 50) |
|  | // 判断图片是否加载完毕,如果加载完毕了再开始显示 |
|  | if(count === imgCount) { |
|  | this.start() |
|  |  } |
|  |  } |
|  |  }  |
|  |  } |
|  |  |
|  | // 第二种方法,使用as直接断言成HTMLImageElement |
|  | //(this.imgURL[key] as HTMLImageElement).src = src |
|  |  |
|  |  } |
|  |  } |
|  | start() { |
|  | if(this.ctx !== null) { |
|  | // 清屏 |
|  | this.ctx.clearRect(0, 0, 600, 600) |
|  | let startX = 0 |
|  | let startY = 0 |
|  | for(let key in this.imgURL) { |
|  | this.ctx.drawImage(this.imgURL[key] as HTMLImageElement, startX, startY, 100, 100) |
|  |  startX += 100 |
|  |  startY += 100 |
|  |  } |
|  |  } |
|  |  } |
|  | } |
|  |  |
|  | new Game() |


五、变形

canvas是可以进行变形的,但是变形的不是元素,而是ctx,ctx就是整个画布的渲染区域,整个画布在变形,我们需要在画布变形前进行保存和恢复:

  • save():保存画布(canvas)的所有状态。
  • restore():save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:

  • 当前应用的变形(即移动,旋转和缩放,见下)
  • 以及下面这些属性:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled
  • 当前的裁切路径(clipping path),会在下一节介绍

你可以调用任意多次 save方法。每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。

以下的例子可以很好的印证这两个的用法:



|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  |  ctx.fillRect(0, 0, 150, 150); // 使用默认设置绘制一个矩形 |
|  |  ctx.save(); // 保存默认状态 |
|  |  |
|  |  ctx.fillStyle = '#09F' // 在原有配置基础上对颜色做改变 |
|  |  ctx.fillRect(15, 15, 120, 120); // 使用新的设置绘制一个矩形 |
|  |  |
|  |  ctx.save(); // 保存当前状态 |
|  |  ctx.fillStyle = '#FFF' // 再次改变颜色配置 |
|  |  ctx.globalAlpha = 0.5; |
|  |  ctx.fillRect(30, 30, 90, 90); // 使用新的配置绘制一个矩形 |
|  |  |
|  |  ctx.restore(); // 重新加载之前的颜色状态 |
|  |  ctx.fillRect(45, 45, 60, 60); // 使用上一次的配置绘制一个矩形 |
|  |  |
|  |  ctx.restore(); // 加载默认颜色配置 |
|  |  ctx.fillRect(60, 60, 30, 30); // 使用加载的配置绘制一个矩形 |
|  | } |


canvas基础简单易懂教程(完结,多图)_第24张图片

5.1 移动translate

translate(x, y): translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量。

在做变形之前先保存状态是一个良好的习惯。大多数情况下,调用 restore 方法比手动恢复原先的状态要简单得多。又,如果你是在一个循环中做位移但没有保存和恢复 canvas 的状态,很可能到最后会发现怎么有些东西不见了,那是因为它很可能已经超出 canvas 范围以外了。

我们知道了变形实际上就是将整个画布进行的变形,所以如果一旦我们的变形操作变多了,画布将变得不可控。

所以如果我们使用到变形,一定记住下面的规律:变形之前要先备份,将世界和平的状态进行备份,然后再变形,变形完毕后再恢复到世界和平的样子,不要影响下一次的操作。



|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  | // 保存 |
|  |  ctx.save() |
|  |  ctx.translate(50, 50) |
|  |  ctx.fillRect(0, 0, 120, 120) |
|  | // 恢复 |
|  |  ctx.restore() |
|  | // 渲染位置是没有存档之前的位置 |
|  |  ctx.fillRect(120, 300, 120, 120) |
|  | } |


canvas基础简单易懂教程(完结,多图)_第25张图片

5.2 旋转 rotate

rotate(angle)这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法。

5.3 缩放 scale

scale(x, y): scale 方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会缩小图形, 如果比1大会放大图形。默认值为1, 为实际大小。

画布初始情况下, 是以左上角坐标为原点的第一象限。如果参数为负实数, 相当于以x 或 y轴作为对称轴镜像反转(例如, 使用translate(0,canvas.height); scale(1,-1); 以y轴作为对称轴镜像反转, 就可得到著名的笛卡尔坐标系,左下角为原点)。

默认情况下,canvas 的 1 个单位为 1 个像素。举例说,如果我们设置缩放因子是 0.5,1 个单位就变成对应 0.5 个像素,这样绘制出来的形状就会是原先的一半。同理,设置为 2.0 时,1 个单位就对应变成了 2 像素,绘制的结果就是图形放大了 2 倍。

5.4 变形 transform

transform(a, b, c, d, e, f)

a (m11): 水平方向的缩放;

b(m12): 竖直方向的倾斜偏移;

c(m21): 水平方向的倾斜偏移;

d(m22): 竖直方向的缩放;

e(dx): 水平方向的移动;

f(dy): 竖直方向的移动.



|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  | // 保存 |
|  |  ctx.save() |
|  |  ctx.transform(0.5, 0, 1, 0.5, 100, 100) |
|  |  ctx.fillRect(0, 0, 100,100) |
|  | // 恢复 |
|  |  ctx.restore() |
|  | // 渲染位置是没有存档之前的位置 |
|  |  ctx.fillRect(0, 200, 100, 100) |
|  |  |
|  | } |


canvas基础简单易懂教程(完结,多图)_第26张图片

5.5 滚动的车轮案例

  • index.html


|  | html> |
|  |  |
|  |  |
|  |  |
|  |  |
|  |  |
|  |  |
|  | canvas的变形-滚动的车轮title> |
|  | <link rel="stylesheet" href="./css/reset.css" type="text/css"> |
|  | <link rel="stylesheet" href="./css/index.css" type="text/css"> |
|  | head> |
|  |  |
|  | <body> |
|  | <canvas id="mycanvas"width="1200" height="600" > |
|  |  当前的浏览器版本不支持,请升级浏览器 |
|  | canvas> |
|  | <script src='./dist/canvas.js'>script> |
|  | body> |
|  | html> |


</code></pre> 
  <ul> 
   <li>所需图片</li> 
  </ul> 
  <p><a href="http://img.e-com-net.com/image/info8/755956050f4845f38be0cf085e5ce4c5.webp" target="_blank"><img src="http://img.e-com-net.com/image/info8/755956050f4845f38be0cf085e5ce4c5.webp" alt="canvas基础简单易懂教程(完结,多图)_第27张图片" width="886" height="890" style="border:1px solid black;"></a></p> 
  <ul> 
   <li>canvas.ts</li> 
  </ul> 
  <pre><code>

|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  |  |
|  | if (ctx !== null) { |
|  | // 第一步是创建一个image元素 |
|  | const image:HTMLImageElement = new Image() |
|  | // 用src设置图片的地址 |
|  |  image.src = "image/汽车车轮.png" |
|  | // 必须要在onload函数内绘制图片,否则不会渲染 |
|  |  image.onload = () => { |
|  | // 定时器 |
|  | // 旋转的度数 |
|  | let deg = 0 |
|  | // 位置 |
|  | let x= -100 |
|  |  |
|  | setInterval(() => { |
|  | // 清除画布 |
|  |  ctx.clearRect(0, 0, myCanvas.width, myCanvas.height) |
|  |  deg += 0.1 |
|  |  x += 5 |
|  | if(x >= myCanvas.width - 100) { |
|  |  x = -100 |
|  |  } |
|  | // 备份 |
|  |  ctx.save() |
|  | // 平移, 目前我们的原点为(100,300) |
|  |  ctx.translate(x, 300) |
|  | // 旋转,因为旋转始终在canvas的原点,所以我们得用translate改变原点。 |
|  |  ctx.rotate(deg) |
|  | // 我们得让车轮的中心处于原点,所以我们需要在第一个和第二个参数各为第三和第四个参数的一半然后再加负号 |
|  |  ctx.drawImage(image, -100, -100, 200, 200) |
|  | // 恢复 |
|  |  ctx.restore() |
|  |  }, 1000/60) |
|  |  } |
|  | } |


</code></pre> 
  <ul> 
   <li>整体架构</li> 
  </ul> 
  <p><a href="http://img.e-com-net.com/image/info8/34c9868282614ad7b86b7690195e19d8.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/34c9868282614ad7b86b7690195e19d8.jpg" alt="canvas基础简单易懂教程(完结,多图)_第28张图片" width="152" height="177" style="border:1px solid black;"></a></p> 
  <ul> 
   <li>实现的效果<br> </li> 
  </ul> 
  <h2>六、合成与裁剪</h2> 
  <p>合成其实就是我们常见的蒙版状态,本质就是如何进行压盖,如何进行显示。</p> 
  <p>在之前我们总是将一个图形画在另一个之上,对于其他更多的情况,仅仅这样是远远不够的。比如,对合成的图形来说,绘制顺序会有限制。不过,我们可以利用 <code>globalCompositeOperation</code> 属性来改变这种状况。此外, <code>clip</code>属性允许我们隐藏不想看到的部分图形。</p> 
  <p>比如我们此时花了一个方和一个圆,第一次画的是方,第二次画的是圆,所以会出现圆压盖方的现象</p> 
  <pre><code>

|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  |  ctx.fillStyle = 'skyblue' |
|  |  ctx.fillRect(100, 100, 100, 100) |
|  |  ctx.fillStyle = 'deeppink' |
|  |  ctx.beginPath() |
|  |  ctx.arc(200, 200, 60, 0, 7,false) |
|  |  ctx.fill() |
|  | } |


</code></pre> 
  <p><a href="http://img.e-com-net.com/image/info8/4d997d679ffa4951b8d8a1e270b6959c.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/4d997d679ffa4951b8d8a1e270b6959c.png" alt="canvas基础简单易懂教程(完结,多图)_第29张图片" width="513" height="523" style="border:1px solid black;"></a></p> 
  <h3>6.1 globalCompositeOperation</h3> 
  <p><code>globalCompositeOperation = type</code></p> 
  <p>这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识12种遮盖方式的字符串。具体情况看MDN。</p> 
  <p>我们可以通过这个属性来对上方设置压盖顺序:</p> 
  <p>比如说此时我们想让粉色在下面, 可以使用destination-over:</p> 
  <pre><code>

|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  |  ctx.fillStyle = 'skyblue' |
|  |  ctx.fillRect(100, 100, 100, 100) |
|  |  ctx.globalCompositeOperation= 'destination-over' |
|  |  ctx.fillStyle = 'deeppink' |
|  |  ctx.beginPath() |
|  |  ctx.arc(200, 200, 60, 0, 7,false) |
|  |  ctx.fill() |
|  | } |


</code></pre> 
  <p><a href="http://img.e-com-net.com/image/info8/6fea087929cb4f1d80c0391c35f66d47.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/6fea087929cb4f1d80c0391c35f66d47.png" alt="canvas基础简单易懂教程(完结,多图)_第30张图片" width="262" height="239" style="border:1px solid black;"></a></p> 
  <h3>6.2 裁剪路径</h3> 
  <p>裁切路径和普通的 canvas 图形差不多,不同的是它的作用是遮罩,用来隐藏不需要的部分。如下图所示。红边五角星就是裁切路径,所有在路径以外的部分都不会在 canvas 上绘制出来。</p> 
  <p><a href="http://img.e-com-net.com/image/info8/5aca7fea7801488b8c6806dd6e45f5fa.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/5aca7fea7801488b8c6806dd6e45f5fa.png" alt="canvas基础简单易懂教程(完结,多图)_第31张图片" width="241" height="245" style="border:1px solid black;"></a></p> 
  <p>如果和上面介绍的 <code>globalCompositeOperation</code> 属性作一比较,它可以实现与 <code>source-in</code> 和 <code>source-atop</code>差不多的效果。最重要的区别是裁切路径不会在 canvas 上绘制东西,而且它永远不受新图形的影响。这些特性使得它在特定区域里绘制图形时相当好用。</p> 
  <p><code>clip()</code>: 将当前正在构建的路径转换为当前的裁剪路径。默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。</p> 
  <h3>6.3 刮刮乐案例</h3> 
  <ul> 
   <li>index.html</li> 
  </ul> 
  <pre><code>

|  | html> |
|  | <html lang="en"> |
|  |  |
|  | <head> |
|  | <meta charset="UTF-8"> |
|  | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|  | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|  | <title>canvas实现刮刮乐title> |
|  | <link rel="stylesheet" href="./css/reset.css" type="text/css"> |
|  | <link rel="stylesheet" href="./css/index.css" type="text/css"> |
|  | head> |
|  |  |
|  | <body> |
|  | <div> |
|  |  特等奖 |
|  | <canvas width="250" height="60" id="mycanvas"> |
|  |  当前的浏览器版本不支持,请升级浏览器 |
|  | canvas> |
|  | div> |
|  | <script src='./dist/canvas.js'>script> |
|  | body> |
|  | html> |


</code></pre> 
  <ul> 
   <li>index.css</li> 
  </ul> 
  <pre><code>

|  | div { |
|  | border: 1px solid #000; |
|  | width: 250px; |
|  | height: 60px; |
|  | font-size: 40px; |
|  | line-height: 60px; |
|  | text-align: center; |
|  | position: relative; |
|  |  user-select: none; |
|  | } |
|  |  |
|  | canvas { |
|  | position: absolute; |
|  | left: 0; |
|  | top: 0; |
|  | } |


</code></pre> 
  <ul> 
   <li>canvas.ts</li> 
  </ul> 
  <pre><code>

|  | // 得到画布 |
|  | const myCanvas: HTMLCanvasElement = document.getElementById('mycanvas') as HTMLCanvasElement |
|  | // 获得上下文 |
|  | const ctx = myCanvas.getContext('2d') |
|  |  |
|  | if (ctx !== null) { |
|  |  ctx.fillStyle = '#333' |
|  |  ctx.fillRect(0, 0, 250, 60) |
|  | // 设置新画上的元素,实际上就是擦除之前的元素 |
|  |  ctx.globalCompositeOperation = 'destination-out' |
|  |  |
|  | const func = (event:any) => { |
|  | // 画图 |
|  |  ctx.beginPath() |
|  |  ctx.arc(event.offsetX, event.offsetY,10, 0, Math.PI * 2,false) |
|  |  ctx.fill() |
|  |  } |
|  | // 按下 |
|  |  myCanvas.onmousedown = () => { |
|  | // 添加鼠标移动事件 |
|  |  myCanvas.addEventListener('mousemove', func) |
|  |  } |
|  | // 松开 |
|  |  myCanvas.onmouseup = () => { |
|  | // 删除鼠标移动事件 |
|  |  myCanvas.removeEventListener('mousemove', func) |
|  |  } |
|  | } |


</code></pre> 
  <ul> 
   <li>实现效果</li> 
  </ul> 
  <p><a href="http://img.e-com-net.com/image/info8/8053df5acdb64f5bb2c5f1f4c9a7f5fa.gif" target="_blank"><img src="http://img.e-com-net.com/image/info8/8053df5acdb64f5bb2c5f1f4c9a7f5fa.gif" alt="" width="281" height="79"></a></p> 
  <h2>七、总结</h2> 
  <p>至此,一个简单的学习canvas教程已经完结,大家还是多看看文档吧,希望这个教程能让大家喜欢上canvas并且好好的利用它!</p> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1666203987755491328"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(计算机,计算机)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1899357944596721664.htm"
                           title="深度解析:DETR的多尺度特征融合" target="_blank">深度解析:DETR的多尺度特征融合</a>
                        <span class="text-muted">AI天才研究院</span>
<a class="tag" taget="_blank" href="/search/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E4%BC%81%E4%B8%9A%E7%BA%A7%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%98/1.htm">AI大模型企业级应用开发实战</a><a class="tag" taget="_blank" href="/search/DeepSeek/1.htm">DeepSeek</a><a class="tag" taget="_blank" href="/search/R1/1.htm">R1</a><a class="tag" taget="_blank" href="/search/%26amp%3B/1.htm">&</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AEAI%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%A4%A7%E6%A8%A1%E5%9E%8B/1.htm">大数据AI人工智能大模型</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E7%A7%91%E5%AD%A6/1.htm">计算科学</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E8%AE%A1%E7%AE%97/1.htm">神经计算</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%9E%8B%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/1.htm">大型语言模型</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/AGI/1.htm">AGI</a><a class="tag" taget="_blank" href="/search/LLM/1.htm">LLM</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/RPA/1.htm">RPA</a>
                        <div>"深度解析:DETR的多尺度特征融合"作者:禅与计算机程序设计艺术1.背景介绍1.1目标检测的挑战与传统方法的局限性目标检测是计算机视觉领域中的一个基本任务,其目标是识别图像或视频中所有感兴趣的目标,并确定它们的位置和类别。传统的目标检测方法,如FasterR-CNN和YOLO,通常依赖于预定义的锚框或候选区域来生成目标proposals。然而,这些方法存在一些固有的局限性:人工先验知识:锚框的设</div>
                    </li>
                    <li><a href="/article/1899317973517135872.htm"
                           title="【C语言】八进制、十六进制" target="_blank">【C语言】八进制、十六进制</a>
                        <span class="text-muted">Octopus2077</span>
<a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/visual/1.htm">visual</a><a class="tag" taget="_blank" href="/search/studio/1.htm">studio</a>
                        <div>前言在我们日常生活中使用的数往往是十进制的,而当我们学习C语言后我们会接触到许多不同的进制并且时常需要去思考与使用这些不同的进制(尤其是2的幂相关的进制,因为这种计数系统比十进制更接近于计算机的二进制系统),所以学习和掌握这些不同进制是非常重要的。本文将对八进制和十六进制(8和16都为2的幂)进行一些讲解。通常情况C语言都假定整型常量是十进制的数,但在表达与计算机相关的值时,八进制和十六进制却十分</div>
                    </li>
                    <li><a href="/article/1899309401106345984.htm"
                           title="Python学习第十一天" target="_blank">Python学习第十一天</a>
                        <span class="text-muted">Leo来编程</span>
<a class="tag" taget="_blank" href="/search/Python%E5%AD%A6%E4%B9%A0/1.htm">Python学习</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>疑惑:有很多人不知道是不是也分不清什么是单核?什么是多核?什么是时间片?进程?线程?那么在讲进程和线程前我先举个例子更好理解这些概念。单核例子:比如你是一个厨师(计算机)在一个厨房(CPU)里需要同时做3个菜(进程)、每个菜需要准备不同的调料以及协作(线程),那么这个厨师需要不断地切换时间(时间片)来达到同时在一个时间将三个菜做完。多核的话其实对应的例子就是多个厨师,这样的例子太多了因为万物皆对象</div>
                    </li>
                    <li><a href="/article/1899309273884717056.htm"
                           title="matlab spmd,matlab并行计算命令" target="_blank">matlab spmd,matlab并行计算命令</a>
                        <span class="text-muted">其实我是老莫</span>
<a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a><a class="tag" taget="_blank" href="/search/spmd/1.htm">spmd</a>
                        <div>1.matlab仿真模型怎么并行计算以单台双核计算机为例。首先打开MATLAB命令窗口,输入matlabpoolopen就OK了。这样,就相当于将一台计算机的两个核心,当做两台机器用啦。接下来是编程序实现的方法。MATLAB并行计算的模式有几种?主要是两种:parfor模式和spmd模式。两种模式的应用都很简单。第一个中,parfor其实就是parallel+for简化而来,顾名思义啊,就是把原来</div>
                    </li>
                    <li><a href="/article/1899306747269541888.htm"
                           title="目标检测项目" target="_blank">目标检测项目</a>
                        <span class="text-muted">sho_re</span>
<a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/pytorch/1.htm">pytorch</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/1.htm">目标检测</a>
                        <div>·识别图片中有哪些物体并且找到物体的存在位置多任务:位置+类别目标种类与数量繁多的问题目标尺度不均的问题遮挡、噪声等外部环境干扰VOC数据集:PASCALVOC挑战赛(ThePASCALVisualObjectClasses)是一个世界级的计算机视觉挑战赛。4大类,20小类VOC2007:9963图片/24640目标VOC2012:23080图片/54900目标·COCO数据集:起源于微软2014</div>
                    </li>
                    <li><a href="/article/1899299059043201024.htm"
                           title="刷题前必学!二叉树!用JavaScript学数据结构与算法" target="_blank">刷题前必学!二叉树!用JavaScript学数据结构与算法</a>
                        <span class="text-muted"></span>

                        <div>‍JavaScript算法与数据结构-HowieCong务必要熟悉JavaScript使用再来学!一、树是什么?数据结构中的树,对于现实世界中的树简化——树根抽象为“根节点”,树枝抽象为“边”,树枝的两个端点抽象为“结点”,树叶抽象为“叶子结点”计算机中的树如下:二、树的重点树的层次计算规则:根结点所在的那一层为第一层,其子节点为第二层,以此类推结点和树的高度计算规则:叶子结点高度为1,每向上一层</div>
                    </li>
                    <li><a href="/article/1899292496433836032.htm"
                           title="从零开始学习黑客技术,看这一篇就够了" target="_blank">从零开始学习黑客技术,看这一篇就够了</a>
                        <span class="text-muted">网络安全-旭师兄</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%AF%86%E7%A0%81%E5%AD%A6/1.htm">密码学</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/1.htm">网络安全</a>
                        <div>基于入门网络安全/黑客打造的:黑客&网络安全入门&进阶学习资源包黑客,对于很多人来说,是一个神秘的代名词,加之影视作品夸张的艺术表现,使得黑客这个本来只专注于技术的群体,散发出亦正亦邪的神秘色彩。黑客源自英文hacker一词,最初曾指热心于计算机技术、水平高超的电脑高手,尤其是程序设计人员,逐渐区分为白帽、灰帽、黑帽等。其中,白帽黑客被称为道德黑客。他们不会非法入侵用户网络,而是通过一系列测试检查</div>
                    </li>
                    <li><a href="/article/1899289094962343936.htm"
                           title="计算机网络:电路交换,报文交换,分组交换" target="_blank">计算机网络:电路交换,报文交换,分组交换</a>
                        <span class="text-muted">LG.YDX</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/1.htm">计算机网络</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/1.htm">计算机网络</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a>
                        <div>一、电路交换:核心思想在通信前建立一条专用物理路径(电路),整个通信过程中独占该路径,结束后释放资源。特点1.建立连接(尝试占用通信资源)2.通信(一直占用通信资源)3.释放连接(归还通信资源)优点:•实时性强(如语音通话、视频会议)。•数据传输顺序和完整性有保障。缺点:•资源浪费(空闲时链路无法被其他用户使用)。•连接建立/释放时间长(不适合突发性数据传输)。线路分配的灵活性差。节点交换不支持“</div>
                    </li>
                    <li><a href="/article/1899275732790603776.htm"
                           title="统信uos20:利用docker部署python+jupyterlab开发环境" target="_blank">统信uos20:利用docker部署python+jupyterlab开发环境</a>
                        <span class="text-muted">阆遤</span>
<a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/jupyter/1.htm">jupyter</a><a class="tag" taget="_blank" href="/search/github/1.htm">github</a><a class="tag" taget="_blank" href="/search/actions/1.htm">actions</a><a class="tag" taget="_blank" href="/search/workflow/1.htm">workflow</a><a class="tag" taget="_blank" href="/search/%E7%BB%9F%E4%BF%A1uos20/1.htm">统信uos20</a>
                        <div>很多统信uos20计算机没有联网安装python开发环境的条件,但是工作中需要对数据进行分析处理,因而产生了离线部署python开发环境的想法。我首先下载了python3.11的源代码包,在uos中编译居然正常通过。但后续的麻烦来了:需要安装的库没法安装。尝试了一天,最终放弃。改用Docker方式部署,理由就不多解释了。一、在uos中安装docker。我的系统是uos20linux4.19.0-a</div>
                    </li>
                    <li><a href="/article/1899245347633426432.htm"
                           title="前端开发使用的 安卓模拟器_【译】移动开发中的仿真器与模拟器" target="_blank">前端开发使用的 安卓模拟器_【译】移动开发中的仿真器与模拟器</a>
                        <span class="text-muted">weixin_39976748</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E4%BD%BF%E7%94%A8%E7%9A%84/1.htm">前端开发使用的</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%8D%93%E6%A8%A1%E6%8B%9F%E5%99%A8/1.htm">安卓模拟器</a>
                        <div>译者注:本文主要涉及到两个概念:Emulator和Simulator。通常我们在工作中可能统统习惯称为“模拟器”,但实际上二者有所不同。为了分清概念,本文将Emulator译作“仿真器”,Simulator译作“模拟器”。听起来可能略拗口,如产生生理或心理不适,敬请谅解。仿真器(Emulator),又称仿真程序,在软件工程中指可以使计算机或者其他多媒体平台(掌上电脑,手机)能够运行其他平台上的程序</div>
                    </li>
                    <li><a href="/article/1899243707782197248.htm"
                           title="(六)Java-BigDecimal" target="_blank">(六)Java-BigDecimal</a>
                        <span class="text-muted">Kyrie_Li</span>
<a class="tag" taget="_blank" href="/search/Java%E4%BD%93%E7%B3%BB/1.htm">Java体系</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>一、概述BigDecimal类用于高精度计算,特别适用于需要进行精确浮点数运算的场合,例如货币计算、金融应用或科学计算。二、优势由于double和float类型是浮点数类型,它们在表示一些十进制数时会出现精度丢失问题,而BigDecimal则可以避免这些问题,提供任意精度的数值表示。三、特点1.任意精度:BigDecimal的精度仅受限于计算机的内存,而不像float和double有固定的精度限制</div>
                    </li>
                    <li><a href="/article/1899221008817123328.htm"
                           title="基于jsp+servlet+mysql实现增删改查" target="_blank">基于jsp+servlet+mysql实现增删改查</a>
                        <span class="text-muted">蟹黄味汉堡</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/servlet/1.htm">servlet</a><a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a>
                        <div>#声明单纯记录学习计算机当中所遇到的问题把解决问题的方法分享给大家希望大佬不要喷我这个小白#链接mysql数据库publicclassBaseDao{publicConnectiongetConnection()throwsClassNotFoundException,SQLException{//url里的demo4为数据库名称Stringurl="jdbc:mysql://localhost:</div>
                    </li>
                    <li><a href="/article/1899209775242080256.htm"
                           title="操作系统概述" target="_blank">操作系统概述</a>
                        <span class="text-muted">Wlq0415</span>
<a class="tag" taget="_blank" href="/search/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/1.htm">操作系统</a><a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a>
                        <div>操作系统定义操作系统(OS)是管理计算机硬件和软件资源的系统软件,旨在提供一个操作环境,使用户和应用程序能够高效地使用计算机资源。它通过合理组织计算机工作流程、控制程序执行并提供友好接口,确保用户能够顺利进行各种操作。操作系统的作用资源管理:操作系统管理计算机中运行的程序,并分配CPU、内存、输入输出设备等各种软硬件资源,确保它们高效运作。人机接口:为用户提供友好的界面,使用户能够方便地与计算机进</div>
                    </li>
                    <li><a href="/article/1899207377740165120.htm"
                           title="基于大数据架构的就业岗位推荐系统的设计与实现【java或python】—计算机毕业设计源码+LW文档" target="_blank">基于大数据架构的就业岗位推荐系统的设计与实现【java或python】—计算机毕业设计源码+LW文档</a>
                        <span class="text-muted">qq_375279829</span>
<a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                        <div>摘要随着互联网技术的迅猛发展和大数据时代的到来,就业市场日益复杂多变,求职者与招聘方之间的信息不对称问题愈发突出。为解决这一难题,本文设计并实现了一个基于大数据架构的就业岗位推荐系统。该系统通过收集、整合并分析大量求职者简历信息、企业招聘信息以及市场动态数据,运用先进的机器学习算法,为求职者提供个性化的岗位推荐服务,同时帮助企业快速定位到合适的候选人。本文将从系统设计的背景与意义、技术基础、需求分</div>
                    </li>
                    <li><a href="/article/1899205234903805952.htm"
                           title="计算机网络 概述" target="_blank">计算机网络 概述</a>
                        <span class="text-muted">kikikidult</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/1.htm">计算机网络</a>
                        <div>目录1.1因特网概述1网络、互连网(互联网)和因特网的区别和关系因特网服务提供者(InternetServiceProvider,ISP)2因特网发展的三个阶段3因特网的标准化工作4因特网的组成1.2三种交换方式1电路交换(CircuitSwitching)2分组交换(PacketSwitching)3报文交换(MessageSwitching)4三种交换方式的对比1.3计算机网络的定义1.4计算</div>
                    </li>
                    <li><a href="/article/1899204729133658112.htm"
                           title="java基础知识点详解一:Java概述及三种技术架构" target="_blank">java基础知识点详解一:Java概述及三种技术架构</a>
                        <span class="text-muted">我是老实人辶</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
                        <div>Java语言是一门随时代快速发展的计算机语言程序,其深刻展示了程序编写的精髓,加上其简明严谨的结构及简洁的语法编写为其将来的发展及维护提供了保障。由于提供了网络应用的支持和多媒体的存取,会推动Internet和企业网络的Web的应用java概述:1991年Sun公司的JamesGosling等人开始开发名称为Oak的语言,希望用于控制嵌入在有线电视交换盒、PDA等的微处理器;1994年将Oak语言</div>
                    </li>
                    <li><a href="/article/1899194636941979648.htm"
                           title="多进程多线程浏览器(比如 Chrome)" target="_blank">多进程多线程浏览器(比如 Chrome)</a>
                        <span class="text-muted">暴走的李丹</span>

                        <div>线程:是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元。多线程:是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。进程:是应用程序的执行实例,每一个进程都是由私有的虚拟地址空间、代码、数据和其它系统资源所组成。多进程:多进程指的是在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于</div>
                    </li>
                    <li><a href="/article/1899179630045229056.htm"
                           title="localhost 已拒绝连接。" target="_blank">localhost 已拒绝连接。</a>
                        <span class="text-muted">滚菩提哦呢</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a>
                        <div>"localhost已拒绝连接"是一个计算机网络错误提示,表示你的本地计算机尝试连接到本地服务器上的某个应用程序,但连接被服务器拒绝了。这种错误通常出现在以下几种情况下:服务器没有启动或者应用程序没有在服务器上运行。服务器上的应用程序正在使用不同的端口,而你尝试连接的端口不正确。防火墙或其他安全软件阻止了你的连接。你输入的URL有误,无法正确识别要连接的服务器。解决此问题的方法包括检查服务器是否启</div>
                    </li>
                    <li><a href="/article/1899157437533974528.htm"
                           title="如何使用Python与MySQL数据库进行查询和更新操作?" target="_blank">如何使用Python与MySQL数据库进行查询和更新操作?</a>
                        <span class="text-muted">程序员总部</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                        <div>在当今的开发环境中,数据库操作是程序员日常工作的一部分。Python作为一种流行的编程语言,提供了众多库来简化与数据库的交互。MySQL,作为一种广泛使用的关系型数据库,尤其受欢迎。那么,如何用Python进行MySQL数据库的查询和更新呢?本文会详细介绍一下这个过程,包括如何设置环境、连接数据库以及进行基本的查询与更新操作。环境准备在开始之前,你需要确保你的计算机上安装了Python和MySQL</div>
                    </li>
                    <li><a href="/article/1899144450890854400.htm"
                           title="《深度解析DeepSeek-M8:量子经典融合,重塑计算能效格局》" target="_blank">《深度解析DeepSeek-M8:量子经典融合,重塑计算能效格局》</a>
                        <span class="text-muted">程序猿阿伟</span>
<a class="tag" taget="_blank" href="/search/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97/1.htm">量子计算</a>
                        <div>在科技飞速发展的今天,量子计算与经典算法的融合成为了前沿领域的焦点。DeepSeek-M8的“量子神经网络混合架构”,宛如一把钥匙,开启了经典算法与量子计算协同推理的全新大门,为诸多复杂问题的解决提供了前所未有的思路。量子计算,基于量子力学的奇妙特性,如量子比特的叠加与纠缠,展现出了超越经典计算的潜力。量子比特能够同时处于多个状态,实现并行计算,这使得量子计算机在处理某些特定问题时,具备指数级加速</div>
                    </li>
                    <li><a href="/article/1899143317824794624.htm"
                           title="DeepSeek源码解析(2)" target="_blank">DeepSeek源码解析(2)</a>
                        <span class="text-muted">白鹭凡</span>
<a class="tag" taget="_blank" href="/search/deepseek/1.htm">deepseek</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a>
                        <div>Tensor(张量)的介绍在计算机科学和机器学习领域,“张量”(Tensor)是一个数学概念,它被用来表示多维数组。在大模型(如深度学习模型)中,张量扮演着核心角色,具体来说:数据表示:张量用于表示输入数据、模型参数和中间计算结果。例如,在图像处理中,一张图片可以被表示为一个三维张量(高度、宽度、颜色通道数),而在自然语言处理中,一段文本可以被编码为一系列词向量组成的二维张量(句子长度、词向量维度</div>
                    </li>
                    <li><a href="/article/1899141552035393536.htm"
                           title="点云语义分割:PointNet++在S3DIS数据集上的训练" target="_blank">点云语义分割:PointNet++在S3DIS数据集上的训练</a>
                        <span class="text-muted">完美代码</span>
<a class="tag" taget="_blank" href="/search/3d/1.htm">3d</a><a class="tag" taget="_blank" href="/search/neo4j/1.htm">neo4j</a><a class="tag" taget="_blank" href="/search/%E7%82%B9%E4%BA%91/1.htm">点云</a>
                        <div>点云语义分割:PointNet++在S3DIS数据集上的训练点云语义分割是计算机视觉领域的一个重要任务,旨在将点云数据中的每个点分配给其对应的语义类别。PointNet++是一种流行的深度学习方法,可用于处理点云数据,并在各种任务中取得了良好的性能。在本文中,我们将探讨如何使用PointNet++模型在S3DIS数据集上进行训练,并提供相应的源代码。数据集介绍S3DIS数据集是一个常用的用于室内场</div>
                    </li>
                    <li><a href="/article/1899140670635962368.htm"
                           title="DeepSeek 的桌面版本,DeepSeek 是一款 AI 驱动的应用程序,可提供智能帮助和交互。此应用程序允许用户直接从他们的桌面访问 DeepSeek 的聊天界面,并支持本地存储和 cookie" target="_blank">DeepSeek 的桌面版本,DeepSeek 是一款 AI 驱动的应用程序,可提供智能帮助和交互。此应用程序允许用户直接从他们的桌面访问 DeepSeek 的聊天界面,并支持本地存储和 cookie</a>
                        <span class="text-muted">struggle2025</span>
<a class="tag" taget="_blank" href="/search/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/1.htm">自然语言处理</a><a class="tag" taget="_blank" href="/search/deepseek/1.htm">deepseek</a>
                        <div>一、软件介绍文末提供下载DeepSeekDesktop是一个跨平台的桌面应用程序,它将DeepSeek的强大功能(您的AI伴侣)直接带到您的计算机上。它专为简单和方便而设计,允许您在本机桌面环境中与DeepSeek交互,并支持localStorage和cookies。人工智能有可能彻底改变我们与技术的交互方式。受到其他AI应用程序的启发,我创建了DeepSeekDesktop,使这个强大的工具更易</div>
                    </li>
                    <li><a href="/article/1899134871779995648.htm"
                           title="基于YOLOv5的烟雾检测系统:从数据集准备到UI界面实现" target="_blank">基于YOLOv5的烟雾检测系统:从数据集准备到UI界面实现</a>
                        <span class="text-muted">深度学习&目标检测实战项目</span>
<a class="tag" taget="_blank" href="/search/YOLO/1.htm">YOLO</a><a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E7%B1%BB/1.htm">分类</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/1.htm">数据挖掘</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E8%B7%9F%E8%B8%AA/1.htm">目标跟踪</a>
                        <div>1.引言烟雾是火灾发生的一个重要早期信号。烟雾检测能够在火灾初期及时识别并报警,为火灾的扑灭争取宝贵的时间。因此,烟雾检测的研究一直是计算机视觉领域中的一个热点问题。近年来,随着深度学习技术的发展,目标检测算法被广泛应用于烟雾检测,尤其是基于YOLOv5的目标检测模型,由于其较高的精度和较低的计算开销,已经成为许多实时检测系统的首选模型。在这篇博客中,我们将介绍如何使用YOLOv5模型进行烟雾检测</div>
                    </li>
                    <li><a href="/article/1899130584307920896.htm"
                           title="C语言零基础入门教程(1)" target="_blank">C语言零基础入门教程(1)</a>
                        <span class="text-muted">岱宗夫up</span>
<a class="tag" taget="_blank" href="/search/C%E8%AF%AD%E8%A8%80/1.htm">C语言</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a>
                        <div>C语言是一种高效、灵活且功能强大的编程语言,广泛应用于系统软件开发、嵌入式系统、算法实现等多个领域。对于初学者来说,学习C语言不仅是掌握一门编程技能,更是开启编程世界大门的重要一步。本教程将从零开始,带你全面了解C语言的基础知识和核心概念,帮助你快速入门。一、C语言简介C语言由美国计算机科学家丹尼斯·里奇(DennisRitchie)于1972年在贝尔实验室开发,最初用于编写UNIX操作系统。它是</div>
                    </li>
                    <li><a href="/article/1899127685775421440.htm"
                           title="计算机二级——Python" target="_blank">计算机二级——Python</a>
                        <span class="text-muted">辛kai瑞</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                        <div>第一章程序设计的基本方法本章大纲程序设计语言Python语言的概述Python开发环境配置程序的基本编写方法一、程序设计语言程序设计语言也叫编程语言。计算机程序按照程序设计语言规则组织起来的一组计算机指令程序设计语言发展经历了机器语言、汇编语言、高级语言的3个阶段二、编译和解释高级语言根据计算机执行机制的不同分为两类:静态语言和脚本语言,静态语言采用编译方式执行,脚本语言采用解释方式执行编译是将源</div>
                    </li>
                    <li><a href="/article/1899127433668390912.htm"
                           title="计算机视觉|3D 点云处理黑科技:PointNet++ 原理剖析与实战指南" target="_blank">计算机视觉|3D 点云处理黑科技:PointNet++ 原理剖析与实战指南</a>
                        <span class="text-muted">紫雾凌寒</span>
<a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/%E7%82%BC%E9%87%91%E5%8E%82/1.htm">炼金厂</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/1.htm">计算机视觉</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/1.htm">计算机视觉</a><a class="tag" taget="_blank" href="/search/3d/1.htm">3d</a><a class="tag" taget="_blank" href="/search/cnn/1.htm">cnn</a><a class="tag" taget="_blank" href="/search/PointNet%2B%2B/1.htm">PointNet++</a><a class="tag" taget="_blank" href="/search/3d%E4%BA%91/1.htm">3d云</a><a class="tag" taget="_blank" href="/search/3d%E4%BA%91%E6%95%B0%E6%8D%AE/1.htm">3d云数据</a>
                        <div>一、引言在当今数字化与智能化快速发展的时代,3D点云处理技术在多个前沿领域中发挥着重要作用。特别是在自动驾驶和机器人视觉等领域,这项技术已成为实现智能化的关键支撑。以自动驾驶为例,车辆需要实时感知周围复杂的环境信息,包括行人、车辆、交通标志和路况等。3D点云数据能够提供高精度的三维空间信息,使自动驾驶车辆更准确地识别和定位周围物体,从而做出安全、合理的行驶决策。在城市街道上,自动驾驶车辆通过3D点</div>
                    </li>
                    <li><a href="/article/1899101589503799296.htm"
                           title="命令行就是cmd?PowerShell面前cmd就是弟弟?" target="_blank">命令行就是cmd?PowerShell面前cmd就是弟弟?</a>
                        <span class="text-muted">不做超级小白</span>
<a class="tag" taget="_blank" href="/search/%E7%94%B5%E8%84%91%E7%9F%A5%E8%AF%86/1.htm">电脑知识</a><a class="tag" taget="_blank" href="/search/bash/1.htm">bash</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>一、先搞懂“命令行”到底指什么日常语境中的“命令行”:广义指通过输入文本指令操作计算机的工具(如Windows的cmd/PowerShell、Linux/macOS的Terminal)。狭义常特指Windows的cmd.exe(尤其对习惯早期系统的用户)。容易混淆的场景:当教程说“用命令行执行”却未明确工具时,可能导致命令在cmd有效但在PowerShell报错(反之亦然)。例如ping、ipco</div>
                    </li>
                    <li><a href="/article/1899088728903708672.htm"
                           title="【基于手势识别的音量控制系统】" target="_blank">【基于手势识别的音量控制系统】</a>
                        <span class="text-muted">合肥玉安人工智能工作室</span>
<a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/OpenCV/1.htm">OpenCV</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/mediapipe/1.htm">mediapipe</a><a class="tag" taget="_blank" href="/search/%E6%89%8B%E5%8A%BF/1.htm">手势</a><a class="tag" taget="_blank" href="/search/%E6%89%8B%E5%8A%BF%E6%8E%A7%E5%88%B6%E9%9F%B3%E9%87%8F/1.htm">手势控制音量</a>
                        <div>基于手势识别的音量控制系统github项目效果这是一个结合了计算机视觉和系统控制的实用项目,通过识别手势来实现音量的无接触控制,同时考虑到了用户隐私,加入了实时人脸遮罩功能。核心功能实现1.手势识别与音量映射系统使用MediaPipe框架进行手部关键点检测,通过计算大拇指和食指之间的距离来控制音量:def_process_landmarks(self,hand_landmarks):#获取手指关键</div>
                    </li>
                    <li><a href="/article/1899062992272683008.htm"
                           title="代码照进现实:对公司管理策略的技术性解构" target="_blank">代码照进现实:对公司管理策略的技术性解构</a>
                        <span class="text-muted">牛马程序员_江</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>代码照进现实:对公司管理策略的技术性解构春节期间拍摄于南京上学的时候觉得计算机专业的一些理论晦涩难懂,跟现实世界的关联太少,每当遇到一些精妙的设计时都会发出一种感叹:究竟是什么脑袋才能想出这么有意思的东西。一晃工作十年,阅历渐丰,隐约发现其实社会中的一些现象其实和软件工程的一些理念有异曲同工之妙,今天就先拿笔者听闻的一些公司管理策略(套路)来简单说说。事件1-系统吞吐量困境这两年部门走了不少人,但</div>
                    </li>
                                <li><a href="/article/96.htm"
                                       title="怎么样才能成为专业的程序员?" target="_blank">怎么样才能成为专业的程序员?</a>
                                    <span class="text-muted">cocos2d-x小菜</span>
<a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a>
                                    <div>  
如何要想成为一名专业的程序员?仅仅会写代码是不够的。从团队合作去解决问题到版本控制,你还得具备其他关键技能的工具包。当我们询问相关的专业开发人员,那些必备的关键技能都是什么的时候,下面是我们了解到的情况。 
  
关于如何学习代码,各种声音很多,然后很多人就被误导为成为专业开发人员懂得一门编程语言就够了?!呵呵,就像其他工作一样,光会一个技能那是远远不够的。如果你想要成为</div>
                                </li>
                                <li><a href="/article/223.htm"
                                       title="java web开发 高并发处理" target="_blank">java web开发 高并发处理</a>
                                    <span class="text-muted">BreakingBad</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91/1.htm">并发</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91/1.htm">开发</a><a class="tag" taget="_blank" href="/search/%E5%A4%84%E7%90%86/1.htm">处理</a><a class="tag" taget="_blank" href="/search/%E9%AB%98/1.htm">高</a>
                                    <div>java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。 一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(</div>
                                </li>
                                <li><a href="/article/350.htm"
                                       title="mysql批量更新" target="_blank">mysql批量更新</a>
                                    <span class="text-muted">ekian</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>mysql更新优化: 
一版的更新的话都是采用update set的方式,但是如果需要批量更新的话,只能for循环的执行更新。或者采用executeBatch的方式,执行更新。无论哪种方式,性能都不见得多好。 
三千多条的更新,需要3分多钟。 
查询了批量更新的优化,有说replace into的方式,即: 
 
 
replace into tableName(id,status) values</div>
                                </li>
                                <li><a href="/article/477.htm"
                                       title="微软BI(3)" target="_blank">微软BI(3)</a>
                                    <span class="text-muted">18289753290</span>
<a class="tag" taget="_blank" href="/search/%E5%BE%AE%E8%BD%AFBI+SSIS/1.htm">微软BI SSIS</a>
                                    <div>1) 
Q:该列违反了完整性约束错误;已获得 OLE DB 记录。源:“Microsoft SQL Server Native Client 11.0” Hresult: 0x80004005 说明:“不能将值 NULL 插入列 'FZCHID',表 'JRB_EnterpriseCredit.dbo.QYFZCH';列不允许有 Null 值。INSERT 失败。”。 
A:一般这类问题的存在是 </div>
                                </li>
                                <li><a href="/article/604.htm"
                                       title="Java中的List" target="_blank">Java中的List</a>
                                    <span class="text-muted">g21121</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>        List是一个有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。 
        与 set 不同,列表通常允许重复</div>
                                </li>
                                <li><a href="/article/731.htm"
                                       title="读书笔记" target="_blank">读书笔记</a>
                                    <span class="text-muted">永夜-极光</span>
<a class="tag" taget="_blank" href="/search/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/1.htm">读书笔记</a>
                                    <div>   1.  K是一家加工厂,需要采购原材料,有A,B,C,D 4家供应商,其中A给出的价格最低,性价比最高,那么假如你是这家企业的采购经理,你会如何决策? 
    
     传统决策: A:100%订单  B,C,D:0% 
  
  &nbs</div>
                                </li>
                                <li><a href="/article/858.htm"
                                       title="centos 安装 Codeblocks" target="_blank">centos 安装 Codeblocks</a>
                                    <span class="text-muted">随便小屋</span>
<a class="tag" taget="_blank" href="/search/codeblocks/1.htm">codeblocks</a>
                                    <div>1.安装gcc,需要c和c++两部分,默认安装下,CentOS不安装编译器的,在终端输入以下命令即可yum install gccyum install gcc-c++ 
  
2.安装gtk2-devel,因为默认已经安装了正式产品需要的支持库,但是没有安装开发所需要的文档.yum install gtk2* 
3. 安装wxGTK 
   yum search w</div>
                                </li>
                                <li><a href="/article/985.htm"
                                       title="23种设计模式的形象比喻" target="_blank">23种设计模式的形象比喻</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a>
                                    <div>1、ABSTRACT FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory    工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:</div>
                                </li>
                                <li><a href="/article/1112.htm"
                                       title="开发管理 CheckLists" target="_blank">开发管理 CheckLists</a>
                                    <span class="text-muted">aoyouzi</span>
<a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E7%AE%A1%E7%90%86+CheckLists/1.htm">开发管理 CheckLists</a>
                                    <div>开发管理 CheckLists(23) -使项目组度过完整的生命周期 
开发管理 CheckLists(22) -组织项目资源 
开发管理 CheckLists(21) -控制项目的范围开发管理 CheckLists(20) -项目利益相关者责任开发管理 CheckLists(19) -选择合适的团队成员开发管理 CheckLists(18) -敏捷开发 Scrum Master 工作开发管理 C</div>
                                </li>
                                <li><a href="/article/1239.htm"
                                       title="js实现切换" target="_blank">js实现切换</a>
                                    <span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E6%A0%8F%E7%9B%AE%E5%88%87%E6%8D%A2/1.htm">栏目切换</a>
                                    <div>js主要功能之一就是实现页面的特效,窗体的切换可以减少页面的大小,被门户网站大量应用思路: 
   1,先将要显示的设置为display:bisible  否则设为none
    2,设置栏目的id  ,js获取栏目的id,如果id为Null就设置为显示
    3,判断js获取的id名字;再设置是否显示
 
  
代码实现: 
  
html代码: 
  <di</div>
                                </li>
                                <li><a href="/article/1366.htm"
                                       title="周鸿祎在360新员工入职培训上的讲话" target="_blank">周鸿祎在360新员工入职培训上的讲话</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/%E6%84%9F%E6%82%9F/1.htm">感悟</a><a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86/1.htm">项目管理</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E7%94%9F/1.htm">人生</a><a class="tag" taget="_blank" href="/search/%E8%81%8C%E5%9C%BA/1.htm">职场</a>
                                    <div>        这篇文章也是最近偶尔看到的,考虑到原博客发布者可能将其删除等原因,也更方便个人查找,特将原文拷贝再发布的。“学东西是为自己的,不要整天以混的姿态来跟公司博弈,就算是混,我觉得你要是能在混的时间里,收获一些别的有利于人生发展的东西,也是不错的,看你怎么把握了”,看了之后,对这句话记忆犹新。  &</div>
                                </li>
                                <li><a href="/article/1493.htm"
                                       title="前端Web开发的页面效果" target="_blank">前端Web开发的页面效果</a>
                                    <span class="text-muted">Bill_chen</span>
<a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/Microsoft/1.htm">Microsoft</a>
                                    <div>1.IE6下png图片的透明显示: 
<img src="图片地址" border="0" style="Filter.Alpha(Opacity)=数值(100),style=数值(3)"/> 
或在<head></head>间加一段JS代码让透明png图片正常显示。 
 
2.<li>标</div>
                                </li>
                                <li><a href="/article/1620.htm"
                                       title="【JVM五】老年代垃圾回收:并发标记清理GC(CMS GC)" target="_blank">【JVM五】老年代垃圾回收:并发标记清理GC(CMS GC)</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6/1.htm">垃圾回收</a>
                                    <div>  CMS概述 
并发标记清理垃圾回收(Concurrent Mark and Sweep GC)算法的主要目标是在GC过程中,减少暂停用户线程的次数以及在不得不暂停用户线程的请夸功能,尽可能短的暂停用户线程的时间。这对于交互式应用,比如web应用来说,是非常重要的。 
  
CMS垃圾回收针对新生代和老年代采用不同的策略。相比同吞吐量垃圾回收,它要复杂的多。吞吐量垃圾回收在执</div>
                                </li>
                                <li><a href="/article/1747.htm"
                                       title="Struts2技术总结" target="_blank">Struts2技术总结</a>
                                    <span class="text-muted">白糖_</span>
<a class="tag" taget="_blank" href="/search/struts2/1.htm">struts2</a>
                                    <div>  
 
 必备jar文件 
   
 早在struts2.0.*的时候,struts2的必备jar包需要如下几个: 
commons-logging-*.jar   Apache旗下commons项目的log日志包 
freemarker-*.jar          </div>
                                </li>
                                <li><a href="/article/1874.htm"
                                       title="Jquery easyui layout应用注意事项" target="_blank">Jquery easyui layout应用注意事项</a>
                                    <span class="text-muted">bozch</span>
<a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/%E6%B5%8F%E8%A7%88%E5%99%A8/1.htm">浏览器</a><a class="tag" taget="_blank" href="/search/easyui/1.htm">easyui</a><a class="tag" taget="_blank" href="/search/layout/1.htm">layout</a>
                                    <div>在jquery easyui中提供了easyui-layout布局,他的布局比较局限,类似java中GUI的border布局。下面对其使用注意事项作简要介绍: 
     如果在现有的工程中前台界面均应用了jquery easyui,那么在布局的时候最好应用jquery eaysui的layout布局,否则在表单页面(编辑、查看、添加等等)在不同的浏览器会出</div>
                                </li>
                                <li><a href="/article/2001.htm"
                                       title="java-拷贝特殊链表:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?" target="_blank">java-拷贝特殊链表:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>
public class CopySpecialLinkedList {

	/**
	 * 题目:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?
拷贝pNext指针非常容易,所以题目的难点是如何拷贝pRand指针。
假设原来链表为A1 -> A2 ->... -> An,新拷贝</div>
                                </li>
                                <li><a href="/article/2128.htm"
                                       title="color" target="_blank">color</a>
                                    <span class="text-muted">Chen.H</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a>
                                    <div><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">    <HTML>    <HEAD>&nbs</div>
                                </li>
                                <li><a href="/article/2255.htm"
                                       title="[信息与战争]移动通讯与网络" target="_blank">[信息与战争]移动通讯与网络</a>
                                    <span class="text-muted">comsci</span>
<a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a>
                                    <div>      两个坚持:手机的电池必须可以取下来 
               光纤不能够入户,只能够到楼宇 
 
      建议大家找这本书看看:<&</div>
                                </li>
                                <li><a href="/article/2382.htm"
                                       title="oracle flashback query(闪回查询)" target="_blank">oracle flashback query(闪回查询)</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/flashback+query/1.htm">flashback query</a><a class="tag" taget="_blank" href="/search/flashback+table/1.htm">flashback table</a>
                                    <div>在Oracle 10g中,Flash back家族分为以下成员: 
Flashback Database 
Flashback Drop 
Flashback Table 
Flashback Query(分Flashback Query,Flashback Version Query,Flashback Transaction Query) 
下面介绍一下Flashback Drop 和Flas</div>
                                </li>
                                <li><a href="/article/2509.htm"
                                       title="zeus持久层DAO单元测试" target="_blank">zeus持久层DAO单元测试</a>
                                    <span class="text-muted">deng520159</span>
<a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a>
                                    <div>zeus代码测试正紧张进行中,但由于工作比较忙,但速度比较慢.现在已经完成读写分离单元测试了,现在把几种情况单元测试的例子发出来,希望有人能进出意见,让它走下去. 
本文是zeus的dao单元测试: 
1.单元测试直接上代码 
  
package com.dengliang.zeus.webdemo.test;


import org.junit.Test;
import o</div>
                                </li>
                                <li><a href="/article/2636.htm"
                                       title="C语言学习三printf函数和scanf函数学习" target="_blank">C语言学习三printf函数和scanf函数学习</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/printf/1.htm">printf</a><a class="tag" taget="_blank" href="/search/scanf/1.htm">scanf</a><a class="tag" taget="_blank" href="/search/language/1.htm">language</a>
                                    <div>printf函数 
/*
	2013年3月10日20:42:32
	地点:北京潘家园
	功能:
	目的:
		测试%x %X %#x %#X的用法
 */

# include <stdio.h>

int main(void)
{

	printf("哈哈!\n");  // \n表示换行

	int i = 10;
	printf</div>
                                </li>
                                <li><a href="/article/2763.htm"
                                       title="那你为什么小时候不好好读书?" target="_blank">那你为什么小时候不好好读书?</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/life/1.htm">life</a>
                                    <div>dady, 我今天捡到了十块钱, 不过我还给那个人了 
good girl! 那个人有没有和你讲thank you啊 
没有啦....他拉我的耳朵我才把钱还给他的, 他哪里会和我讲thank you 
  
爸爸, 如果地上有一张5块一张10块你拿哪一张呢.... 
当然是拿十块的咯... 
爸爸你很笨的, 你不会两张都拿 
  
爸爸为什么上个月那个人来跟你讨钱, 你告诉他没</div>
                                </li>
                                <li><a href="/article/2890.htm"
                                       title="iptables开放端口" target="_blank">iptables开放端口</a>
                                    <span class="text-muted">Fanyucai</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/iptables/1.htm">iptables</a><a class="tag" taget="_blank" href="/search/%E7%AB%AF%E5%8F%A3/1.htm">端口</a>
                                    <div>1,找到配置文件 
vi /etc/sysconfig/iptables   
  
2,添加端口开放,增加一行,开放18081端口 
-A INPUT -m state --state NEW -m tcp -p tcp --dport 18081 -j ACCEPT 
  
3,保存 
ESC
:wq! 
  
4,重启服务 
service iptables </div>
                                </li>
                                <li><a href="/article/3017.htm"
                                       title="Ehcache(05)——缓存的查询" target="_blank">Ehcache(05)——缓存的查询</a>
                                    <span class="text-muted">234390216</span>
<a class="tag" taget="_blank" href="/search/%E6%8E%92%E5%BA%8F/1.htm">排序</a><a class="tag" taget="_blank" href="/search/ehcache/1.htm">ehcache</a><a class="tag" taget="_blank" href="/search/%E7%BB%9F%E8%AE%A1/1.htm">统计</a><a class="tag" taget="_blank" href="/search/query/1.htm">query</a>
                                    <div>缓存的查询 
目录 
1.    使Cache可查询 
1.1     基于Xml配置 
1.2     基于代码的配置 
2     指定可搜索的属性 
2.1     可查询属性类型 
2.2 &</div>
                                </li>
                                <li><a href="/article/3144.htm"
                                       title="通过hashset找到数组中重复的元素" target="_blank">通过hashset找到数组中重复的元素</a>
                                    <span class="text-muted">jackyrong</span>
<a class="tag" taget="_blank" href="/search/hashset/1.htm">hashset</a>
                                    <div>  如何在hashset中快速找到重复的元素呢?方法很多,下面是其中一个办法: 
 
 


 int[] array = {1,1,2,3,4,5,6,7,8,8};
         
        Set<Integer> set = new HashSet<Integer>();
         
        for(int i = 0</div>
                                </li>
                                <li><a href="/article/3271.htm"
                                       title="使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL" target="_blank">使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL</a>
                                    <span class="text-muted">lanrikey</span>
<a class="tag" taget="_blank" href="/search/history/1.htm">history</a>
                                    <div>后退时关闭当前页面 
<script type="text/javascript"> 
 jQuery(document).ready(function ($) { 
        if (window.history && window.history.pushState) {</div>
                                </li>
                                <li><a href="/article/3398.htm"
                                       title="应用程序的通信成本" target="_blank">应用程序的通信成本</a>
                                    <span class="text-muted">netkiller.github.com</span>
<a class="tag" taget="_blank" href="/search/%E8%99%9A%E6%8B%9F%E6%9C%BA/1.htm">虚拟机</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/%E9%99%88%E6%99%AF%E5%B3%B0/1.htm">陈景峰</a><a class="tag" taget="_blank" href="/search/netkiller/1.htm">netkiller</a><a class="tag" taget="_blank" href="/search/neo/1.htm">neo</a>
                                    <div>应用程序的通信成本  
什么是通信 
一个程序中两个以上功能相互传递信号或数据叫做通信。  
什么是成本 
这是是指时间成本与空间成本。 时间就是传递数据所花费的时间。空间是指传递过程耗费容量大小。  
都有哪些通信方式 
 
 全局变量 
 线程间通信 
 共享内存 
 共享文件 
 管道 
 Socket 
 硬件(串口,USB) 等等 
  
全局变量 
全局变量是成本最低通信方法,通过设置</div>
                                </li>
                                <li><a href="/article/3525.htm"
                                       title="一维数组与二维数组的声明与定义" target="_blank">一维数组与二维数组的声明与定义</a>
                                    <span class="text-muted">恋洁e生</span>
<a class="tag" taget="_blank" href="/search/%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84/1.htm">二维数组</a><a class="tag" taget="_blank" href="/search/%E4%B8%80%E7%BB%B4%E6%95%B0%E7%BB%84/1.htm">一维数组</a><a class="tag" taget="_blank" href="/search/%E5%AE%9A%E4%B9%89/1.htm">定义</a><a class="tag" taget="_blank" href="/search/%E5%A3%B0%E6%98%8E/1.htm">声明</a><a class="tag" taget="_blank" href="/search/%E5%88%9D%E5%A7%8B%E5%8C%96/1.htm">初始化</a>
                                    <div>/**  *   */ package test20111005; /**  * @author FlyingFire  * @date:2011-11-18 上午04:33:36  * @author :代码整理  * @introduce :一维数组与二维数组的初始化  *summary:  */ public c</div>
                                </li>
                                <li><a href="/article/3652.htm"
                                       title="Spring Mybatis独立事务配置" target="_blank">Spring Mybatis独立事务配置</a>
                                    <span class="text-muted">toknowme</span>
<a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a>
                                    <div>在项目中有很多地方会使用到独立事务,下面以获取主键为例      
(1)修改配置文件spring-mybatis.xml    <!-- 开启事务支持 -->    <tx:annotation-driven transaction-manager="transactionManager" />       &n</div>
                                </li>
                                <li><a href="/article/3779.htm"
                                       title="更新Anadroid SDK Tooks之后,Eclipse提示No update were found" target="_blank">更新Anadroid SDK Tooks之后,Eclipse提示No update were found</a>
                                    <span class="text-muted">xp9802</span>
<a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a>
                                    <div>使用Android SDK Manager 更新了Anadroid SDK Tooks 之后, 
打开eclipse提示 This Android SDK requires Android Developer Toolkit version 23.0.0 or above, 点击Check for Updates  
检测一会后提示 No update were found  </div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>