캔버스를 너무 많이 사용하면 자동으로 성능 문제를 고려하게 됩니다. 캔버스 애니메이션을 최적화하는 방법은 무엇입니까?
【캐시 사용하기】
캐시를 사용한다는 것은 사전 렌더링에 오프스크린 캔버스를 사용한다는 의미입니다. 즉, 먼저 오프스크린 캔버스에 그린 다음 drawImage를 통해 오프스크린 캔버스를 메인 캔버스에 그리는 것입니다. 많은 사람들이 이것을 오해할 수도 있습니다. 이것은 게임에서 많이 사용되는 이중 버퍼링 메커니즘이 아닌가요?
실제로 게임 프로그래밍에서는 화면 깜박임을 방지하기 위해 이중 버퍼링 메커니즘이 사용됩니다. 따라서 사용자 앞에 캔버스가 표시되고 그림을 그릴 때 화면 내용이 먼저 그려집니다. 배경 캔버스를 그리면 캔버스의 데이터가 전면 캔버스에 그려집니다. 이는 이중 버퍼링이지만 캔버스에는 이중 버퍼링이 없습니다. 최신 브라우저에는 기본적으로 이중 버퍼링 메커니즘이 내장되어 있기 때문입니다. 따라서 오프스크린 캔버스를 사용하는 것은 더블 버퍼링이 아니라 오프스크린 캔버스를 캐시 영역으로 취급하는 것입니다. 캔버스 API 호출 소모를 줄이기 위해 반복적으로 그려야 하는 캐시 화면 데이터입니다.
우리 모두 알고 있듯이 캔버스 API를 호출하면 성능이 소모됩니다. 따라서 반복되는 화면 데이터를 그리려는 경우 오프 스크린 캔버스를 적절하게 사용하면 다음 DEMO를 살펴볼 수 있습니다.
2.캐시를 사용하지만 오프스크린 캔버스의 너비와 높이가 설정되지 않았습니다
3. 캐시를 사용하지만 오프스크린 캔버스의 너비와 높이가 설정되지 않았습니다
4. 캐싱을 사용하고 오프스크린 캔버스의 너비와 높이를 설정합니다
위 DEMO의 성능이 다르다는 것을 알 수 있습니다. 아래에서 이유를 분석해 보겠습니다. 각 원의 스타일을 구현하기 위해 원을 그릴 때 캐싱이 활성화되지 않은 경우 루프 그리기를 사용했습니다. 페이지의 원이 특정 지점에 도달하면 애니메이션의 각 프레임마다 많은 수의 캔버스 API 호출이 필요하고 많은 양의 계산이 필요하므로 브라우저가 아무리 좋아도 가져옵니다. 아래에.
XML/HTML 코드클립보드에 콘텐츠 복사
- ctx.save();
- var j=0;
- ctx.lineWidth = borderWidth;
- for(var i=1;ithis.r;i =borderWidth){
- ctx.beginPath();
- ctx.StrokeStyle = 이것.color[j];
- ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
- ctx.Stroke();
- j ;
- }
- ctx.restore();
所以, 내 방식의 방법은 다음과 같습니다.
除了创建离屏canvas works 为缓存 륙외, 하단의 현대적인 码中有一点很关键, 就是要设置离屏canvas적 크기와 높이, canvas生成后的默认大小是300 X150; 对于我的代码中每个缓存起来圈圈对象半径最大也就不超过80,所以300X150的大区域,会造成资源浪费,所以就要设置一下离屏캔버스의 크기와 높이, 让它跟缓存起来적 元素大小一致,这样也有利于提高动画性能。上side 4个demo很明显的显示了性能差距,如果没有设置宽高,当页side超过400个圈圈对象时就会卡的不行了,而设置了宽高1000个圈圈对象也不觉得卡。
- var 공 = 함수(x , y , vx , vy , useCache){
- this.x = x;
- this.y = y;
- this.vx = vx;
- this.vy = vy;
- this.r = getZ(getRandom(20,40));
- this.color = [];
- this.cacheCanvas = document.createElement("canvas");
- thisthis.cacheCtx = this.cacheCanvas.getContext("2d");
- this.cacheCanvas.width = 2*this.r;
- this.cacheCanvas.height = 2*this.r;
- var num = getZ(this.r/borderWidth);
- for(var j=0;j번호;j ){
- this.color.push("rgba(" getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) ",1)");
- }
- this.useCache = useCache;
- if(useCache){
- this.cache();
- }
- }
원 개체를 인스턴스화할 때 캐시 메서드를 직접 호출하고 원 개체의 오프스크린 캔버스에 복잡한 원을 직접 그려서 저장합니다.
- 캐시:함수(){
- this.cacheCtx.save()
- var j=0;
- this.cacheCtx.lineWidth = borderWidth for(var
- i=1;ithis.r;i =borderWidth){ this.cacheCtx.beginPath()
- thisthis.cacheCtx.StrokeStyle = this.color[j]; this.cacheCtx.arc(this.r, this.r, i, 0, 2*Math.PI)
- this.cacheCtx.Stroke()
- 제
- this.cacheCtx.restore()
- 그런 다음 다음 애니메이션에서는 원 개체의 오프스크린 캔버스를 기본 캔버스에 그리기만 하면 됩니다. 이런 식으로 각 프레임에서 호출되는 canvasAPI에는 다음 문장만 있습니다.
- XML/HTML 코드
- 이전 for 루프 그리기에 비해 정말 훨씬 빠릅니다. 따라서 벡터 그래픽을 반복적으로 그리거나 여러 그림을 그려야 하는 경우 오프스크린 캔버스를 합리적으로 사용하여 그림 데이터를 미리 캐시할 수 있으므로 각 후속 작업에서 불필요한 성능 소비를 많이 줄일 수 있습니다. 원 개체 1000개에 대한 매끄러운 버전 코드는 다음과 같습니다.
- html>
- html lang="ko" >
- 머리>
- 메타 문자 집합="UTF- 8">
- 스타일>
- 몸{
- 패딩:0;
- 여백:0;
- 오버플로: 숨김;
- }
- #cas{
- 디스플레이: 차단;
- 배경색:rgba(0,0,0,0);
- 여백:자동;
- 테두리:1px 단색;
- }
- 스타일>
- 제목>테스트제목>
- 머리>
- 몸>
- div >
- 캔버스 id='cas' 너비="800" 높이="600">브라우저가 캔버스를 지원하지 않습니다캔버스 > ;
- div style="text- align:center">1000개의 원 개체가 붙어 있지 않습니다div>
- div>
- 스크립트>
- var testBox = 함수(){
- var 캔버스 = 문서.getElementById("cas"),
- ctx = 캔버스.getContext('2d'),
- 테두리 너비 = 2,
- 공 = []
- var 공 = 함수(x, y, vx, vy, useCache){
- this.x = x
- this.y = y;
-
this.vx = vx
- this.vy = vy;
- this.r = getZ(getRandom(20,40));
- this.color = [];
- this.cacheCanvas = document.createElement("canvas");
- thisthis.cacheCtx = this.cacheCanvas.getContext("2d");
- this.cacheCanvas.width = 2*this.r;
- this.cacheCanvas.height = 2*this.r;
- var num = getZ(this.r/borderWidth);
- for(var j=0;j번호;j ){
- this.color.push("rgba(" getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) ",1)");
- }
- this.useCache = useCache;
- if(useCache){
- this.cache();
- }
- }
- 함수 getZ(num){
- var 반올림;
- 반올림 = (0.5 num) | 0;
- // 더블비트가 아닙니다.
- 반올림 = ~~ (0.5 num);
- // 마지막으로 왼쪽 비트 시프트입니다.
- 반올림 = (0.5 num) 0;
- 반올림하여 반환합니다.
- }
- ball.prototype = {
- 페인트:기능(ctx){
- if(!this.useCache){
- ctx.save();
- var j=0;
- ctx.lineWidth = borderWidth;
- for(var i=1;ithis.r;i =borderWidth){
- ctx.beginPath();
- ctx.StrokeStyle = 이것.color[j];
- ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
- ctx.Stroke();
- j ;
- }
- ctx.restore();
- } 그 외{
- ctx.drawImage(this.cacheCanvas , this.x-this.r , this.y-this.r);
- }
- },
- 캐시:기능(){
- this.cacheCtx.save();
- var j=0;
- this.cacheCtx.lineWidth = borderWidth;
- for(var i=1;ithis.r;i =borderWidth){
- this.cacheCtx.beginPath();
- thisthis.cacheCtx.StrokeStyle = this.color[j];
- this.cacheCtx.arc(this.r , this.r , i , 0 , 2*Math.PI);
- this.cacheCtx.Stroke();
- j ;
- }
- this.cacheCtx.restore();
- },
- 이동:기능(){
- this.x = this.vx;
- this.y = this.vy;
- if(this.x>(canvas.width-this.r)||this.x this.r){
- thisthis.x=this.xthis.r?this.r:(canvas.width-this.r);
- this.vx = -this.vx;
- }
- if(this.y>(canvas.height-this.r)||this.y this.r){
- thisthis.y=this.ythis.r?this.r:(canvas.height-this.r);
- this.vy = -this.vy;
- }
- this.paint(ctx);
- }
- }
- var 게임 = {
- init:function(){
- for(var i=0;i1000;i ){
- var b = new ball(getRandom(0,canvas.width) , getRandom(0,canvas .height) , getRandom(-10 , 10) , getRandom(-10 , 10) , true)
- Balls.push(b);
- }
- },
- 업데이트:기능(){
- ctx.clearRect(0,0,canvas.width,canvas.height);
- for(var i=0;i공.길이;i ){
- 공[i].move();
- }
- },
- loop:function(){
- var _this = this;
- this.update();
- RAF(함수(){
- _this.loop();
- })
- },
- start:function(){
- this.init();
- this.loop();
- }
- }
- window.RAF = (function(){
- return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || 함수 (콜백) {window.setTimeout(콜백, 1000 / 60); };
- })();
- 게임 반환;
- }();
- 함수 getRandom(a , b){
- 반환 Math.random()*(ba) a;
- }
- window.onload = 함수(){
- testBox.start();
- }
- 스크립트>
- 몸>
- html>
오프 스크린 캔버스에 대한 또 다른 참고 사항이 있습니다. 지속적으로 객체를 생성하고 파괴하는 것이라면, 적어도 위에서 쓴 것처럼 각 객체의 속성을 바인딩하지 않도록 주의하세요. 오프스크린 캔버스를 설정합니다.
이렇게 바인딩하면 객체가 소멸되면 오프스크린 캔버스도 소멸되며, 수많은 오프스크린 캔버스가 지속적으로 생성 및 소멸되므로 캔버스 버퍼가 GPU 리소스가 많아 브라우저가 쉽게 충돌하거나 심각한 프레임 정지가 발생할 수 있습니다. 해결책은 오프스크린 캔버스 배열을 만들고, 충분한 수의 오프스크린 캔버스를 미리 로드하고, 아직 살아있는 객체만 캐시하고, 객체가 소멸되면 캐시를 취소하는 것입니다. 이로 인해 오프스크린 캔버스가 파괴되지는 않습니다.
【requestAnimationFrame 사용】
이에 대해서는 자세히 설명하지 않겠습니다. setTimeout이나 setInterval이 아닌 이것이 애니메이션에 가장 적합한 루프라는 것을 많은 사람들이 알고 있을 것입니다. 호환성 작성법 직접 게시:
- window.RAF = (function(){
- window.requestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || 함수(콜백)
- })()
【부동소수점 연산 피하기】
JavaScript는 Math.floor, Math.ceil 및parseInt와 같은 몇 가지 매우 편리한 반올림 메서드를 제공하지만 외국 친구들은 테스트를 수행했으며parseInt 메서드는 몇 가지 추가 작업(예: 데이터가 유효한 값인지 감지하고,parseInt)을 수행합니다. 심지어 매개변수를 먼저 문자열로 변환하기도 합니다!) 따라서 직접parseInt를 사용하는 것은 상대적으로 성능 집약적입니다. 따라서 반올림하는 방법은 외국인이 작성한 매우 영리한 방법을 직접 사용할 수 있습니다.
1.반올림 = (0.5 somenum)
2.반올림 = ~~ (0.5 somenum) 3.rounded = (0.5 somenum)
【canvasAPI 호출을 최대한 줄입니다】
파티클 효과를 만들 때는 원을 최대한 적게 사용하고, 파티클이 너무 작기 때문에 사각형을 사용하는 것이 좋습니다. 그 이유는 이해하기 쉽습니다. 원을 그리려면 세 단계가 필요합니다. 먼저 startPath를 사용한 다음 arc를 사용하여 호를 그린 다음 fill을 사용하여 원을 만듭니다. 하지만 정사각형을 그리려면 fillRect가 하나만 필요합니다. 두 호출의 차이만 있을 뿐이지만 입자 개체의 수가 일정 수준에 도달하면 성능 격차가 나타납니다.
그 밖에도 주의할 사항이 있는데, Google에 꽤 많이 있기 때문에 모두 나열하지는 않겠습니다. 이는 나 자신을 위한 기록이라 할 수 있으며, 주로 캐시의 사용량을 기록하기 위한 것이다. 캔버스의 성능을 향상시키려면 가장 중요한 것은 코드 구조에 주의를 기울이고, 불필요한 API 호출을 줄이고, 각 프레임의 복잡한 작업을 줄이거나, 복잡한 작업을 프레임당 한 번에서 여러 프레임에 한 번으로 변경하는 것입니다. 프레임. 동시에 위에서 언급한 캐시 활용을 위해 각 개체에 대해 오프스크린 캔버스를 사용했습니다. 실제로 오프스크린 캔버스를 너무 많이 사용하면 너무 광범위하게 사용할 수 없습니다. 성능 문제가 발생할 수 있으니 최대한 오프스크린 캔버스를 활용해 보세요.
소스코드 주소 : https://github.com/whxaxes/canvas-test/tree/gh-pages/src/Other-demo/cache

html5的div元素默认一行不可以放两个。div是一个块级元素,一个元素会独占一行,两个div默认无法在同一行显示;但可以通过给div元素添加“display:inline;”样式,将其转为行内元素,就可以实现多个div在同一行显示了。

html5中列表和表格的区别:1、表格主要是用于显示数据的,而列表主要是用于给数据进行布局;2、表格是使用table标签配合tr、td、th等标签进行定义的,列表是利用li标签配合ol、ul等标签进行定义的。

固定方法:1、使用header标签定义文档头部内容,并添加“position:fixed;top:0;”样式让其固定不动;2、使用footer标签定义尾部内容,并添加“position: fixed;bottom: 0;”样式让其固定不动。

html5中不支持的标签有:1、acronym,用于定义首字母缩写,可用abbr替代;2、basefont,可利用css样式替代;3、applet,可用object替代;4、dir,定义目录列表,可用ul替代;5、big,定义大号文本等等。

HTML5中画布标签是“<canvas>”。canvas标签用于图形的绘制,它只是一个矩形的图形容器,绘制图形必须通过脚本(通常是JavaScript)来完成;开发者可利用多种js方法来在canvas中绘制路径、盒、圆、字符以及添加图像等。

html5废弃了dir列表标签。dir标签被用来定义目录列表,一般和li标签配合使用,在dir标签对中通过li标签来设置列表项,语法“<dir><li>列表项值</li>...</dir>”。HTML5已经不支持dir,可使用ul标签取代。

3种取消方法:1、给td元素添加“border:none”无边框样式即可,语法“td{border:none}”。2、给td元素添加“border:0”样式,语法“td{border:0;}”,将td边框的宽度设置为0即可。3、给td元素添加“border:transparent”样式,语法“td{border:transparent;}”,将td边框的颜色设置为透明即可。

因为html5不基于SGML(标准通用置标语言),不需要对DTD进行引用,但是需要doctype来规范浏览器的行为,也即按照正常的方式来运行,因此html5只需要写doctype即可。“!DOCTYPE”是一种标准通用标记语言的文档类型声明,用于告诉浏览器编写页面所用的标记的版本。


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.
