1. ホーム
  2. Web制作
  3. html5

ダブルキャッシュを使用したCanvas clearRectによるスプラッシュスクリーンの問題を解決しました。

2022-01-31 04:54:45

前置き

今日、H5でcanvasを使った作業をしていて、スプラッシュスクリーンの問題に遭遇しました。チカチカするのは以下のような感じです。

イシュー・ブリーフ

機能プロファイル

H5 この部分の機能は、副次的なメニューをクリックすることで、画像のマスクを切り替えたり、背景を変更したりすることです。

機能がシンプルなため、この機能の実装にはネイティブキャンバスを使用しました。ただし //n=1e9 simulate map map<int,int> mp;//1e9 occurs at most 1e9 times int main() { IO; int n,cnt=0;//cnt at most 1e9 cin>>n; //1098 mp[n]++; cnt++; while(n) { n++; while(n%10==0) n=n/10; if(mp[n]) break; mp[n]++; cnt++; } cout<<cnt<<endl; return 0; } を使用してキャンバスをクリアすると、ちらつきが発生します。

コードの実装(問題コード)

以下のコードは、スプラッシュ画面を表示するためのキーコードで、onloadによる画像の定義は省略されています。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f3f;
const int INF=0x3f3f3f3f3f;
const ll mod=1e9+7;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
ll gcd(ll a,ll b)
{
	return b!=0?gcd(b,a%b):a;

}
char a[9];
int main()
{
	IO;
	int n,f=0;
	string s;
	cin>>n;
	cin>>s;
	for(int i=1;i<=9;i++)
	{
		cin>>a[i];
	}
	for(int i=0;i<n;i++)
	{
		if(s[i]<a[s[i]-'0'])//guarantee that the change is to the highest bit 
		{
			s[i]=a[s[i]-'0'];
			f=1;//see how long the interval can be continuous 
		}
		else if(f==1 && s[i]>a[s[i]-'0'])//can't just start when s[i] is big no need to replace this valuable once still useless break off  
		{ // unless it has been modified this time can not be modified  
			break;
		}
		
	}
	cout<<s<<endl;
	return 0; 
}


課題分析

簡単な解析の結果、スプラッシュスクリーンが発生する原因は queue<char> q; int a[maxn]; int main() { IO; int n,f=0; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } int l=1,r=n,temp=0,cnt=0; while(n--) { if(a[l]>temp && a[r]>temp) { if(a[l]<a[r]) { temp=a[l]; cnt++; l++; q.push('L'); } else { temp=a[r]; cnt++; r--; q.push('R'); } } else if(a[l]>temp) { temp=a[l]; cnt++; l++; q.push('L'); } else if(a[r]>temp) { temp=a[r]; cnt++; r--; q.push('R'); } else break; } cout<<cnt<<endl; while(!q.empty()) { cout<<q.front(); q.pop(); } cout<<endl; return 0; } キャンバスをクリアした後、描画に時間がかかるためスプラッシュスクリーンが発生します。

ダブルキャッシングとは

を見てみましょう。 マイクロソフト サイト内 ダブルバッファードグラフィックス ダブルキャッシュについて解説しています。

グラフィックのプログラミングを行う際、フリッカーが発生することはよくある問題です。複数の複雑な描画操作を必要とするグラフィックス操作では、レンダリングされた画像がちらついたり、許容できない外観になったりすることがあります。これらの問題に対処するため、.NET Frameworkはダブルキャッシュを提供しています。

ダブルバッファリングは、コンテンツバッファリングを使用して、複数の描画操作に関連するフリッカーの問題に対処します。ダブルバッファリングが有効な場合、すべての描画操作は、まず、画面上の描画面ではなく、メモリキャッシュにレンダリングされます。すべての描画操作が完了すると、メモリバッファはそれに関連する描画面に直接コピーされます。画面上では1つの描画操作しか行われないため、複雑な描画操作に伴う画像のちらつきをなくすことができる。

<スパン デュアルキャッシュの問題点を解決

上記の引用ですが、要するに、描画時間が長いためにスプラッシュ画面が発生することが一番の問題で、その解決策として、キャンバスを キャッシュキャンバス を介して渡される キャンバスをキャッシュする を描画し、描画が完了したら直接 キャンバスをキャッシュする を元のキャンバスに貼り付けることで、描画時間が長いために起こるスプラッシュスクリーンの問題を解決しています。

コードの実装

以下のコードは、画像の定義とonloadを省略した、キーコードです。

updateCanvas(){
    const canvas = document.getElementById('canvas'); // Get the canvas in the page
    const ctx = canvas.getContext('2d');
    
    const tempCanvas = document.createElement('canvas'); // create a new canvas as a cache canvas
    const tempCtx = tempCanvas.getContext('2d');
    tempCanvas.width = 1448; tempCanvas.height = 750; // set the width and height

    // Start drawing
    tempCtx.drawImage(bg,0,0); // background
    ... // omit the rest of the drawing process
    
    // cache the canvas to finish drawing
    
    ctx.clearRect(0,0,1448,750); // Clear the old canvas
    ctx.drawImage(tempCanvas,0,0); // copy the cached canvas to the old one
}

効果の受容

スプラッシュスクリーンの問題が解決されたことがよくわかりますね!

概要

キャンバスの再描画時に clearRect を使用してキャンバスをクリアします。この時点ではキャンバスは空ですが、再描画を開始した後、コンテンツが増えるとそれに伴って時間が長くなるため、視覚的なギャップが生じ、スプラッシュ画面が表示されることになります。

スプラッシュスクリーンを解決することで、本当に描画時間が長くなる問題を解決する方法です。

のグラフィックス画像処理プログラミングを紹介します。 ダブルキャッシング の概念に基づき、描画処理は キャッシュ・キャンバス というように、ページ上のキャンバスが描画処理から排除され キャンバスをキャッシュする が追加されないので、描画処理が見られず、スプラッシュスクリーンの問題が解決されます。

今回の記事は以上です。皆さんの勉強のお役に立てれば幸いです。そして、スクリプトハウスを応援していただければ幸いです。