perf(CustomGameModal): optimize difficulty map rendering with caching
This commit is contained in:
@@ -14,6 +14,7 @@ const fillRate = ref(50);
|
|||||||
const errorMsg = ref('');
|
const errorMsg = ref('');
|
||||||
const difficultyCanvas = ref(null);
|
const difficultyCanvas = ref(null);
|
||||||
const isDragging = ref(false);
|
const isDragging = ref(false);
|
||||||
|
const cachedBackground = ref(null);
|
||||||
|
|
||||||
const drawMap = () => {
|
const drawMap = () => {
|
||||||
const canvas = difficultyCanvas.value;
|
const canvas = difficultyCanvas.value;
|
||||||
@@ -25,46 +26,42 @@ const drawMap = () => {
|
|||||||
// Clear
|
// Clear
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
// Draw Gradient Background
|
// Use cached background if available
|
||||||
// Optimization: Create an image data once if static, but here it's small enough.
|
if (cachedBackground.value) {
|
||||||
const imgData = ctx.createImageData(width, height);
|
ctx.putImageData(cachedBackground.value, 0, 0);
|
||||||
const data = imgData.data;
|
} else {
|
||||||
|
// Draw Gradient Background (Heavy calculation)
|
||||||
|
const imgData = ctx.createImageData(width, height);
|
||||||
|
const data = imgData.data;
|
||||||
|
|
||||||
// Ranges:
|
// Ranges:
|
||||||
// X: Fill Rate 10% -> 90%
|
// X: Fill Rate 10% -> 90%
|
||||||
// Y: Size 5 -> 80
|
// Y: Size 5 -> 80
|
||||||
|
|
||||||
for (let y = 0; y < height; y++) {
|
for (let y = 0; y < height; y++) {
|
||||||
for (let x = 0; x < width; x++) {
|
for (let x = 0; x < width; x++) {
|
||||||
// Map x, y to fillRate, size
|
const normalizedX = x / width;
|
||||||
// y=0 -> size 80 (top), y=height -> size 5 (bottom)
|
const normalizedY = 1 - (y / height); // 0 at bottom, 1 at top
|
||||||
// x=0 -> fill 10%, x=width -> fill 90%
|
|
||||||
|
|
||||||
const normalizedX = x / width;
|
const fRate = 0.1 + normalizedX * 0.8; // 0.1 to 0.9
|
||||||
const normalizedY = 1 - (y / height); // 0 at bottom, 1 at top
|
const sSize = 5 + normalizedY * 75; // 5 to 80
|
||||||
|
|
||||||
const fRate = 0.1 + normalizedX * 0.8; // 0.1 to 0.9
|
const { value } = calculateDifficulty(fRate, sSize);
|
||||||
const sSize = 5 + normalizedY * 75; // 5 to 80
|
|
||||||
|
|
||||||
const { value } = calculateDifficulty(fRate, sSize);
|
// Color Mapping
|
||||||
|
const hue = 120 * (1 - value / 100);
|
||||||
|
const [r, g, b] = hslToRgb(hue / 360, 1, 0.5);
|
||||||
|
|
||||||
// Color Mapping:
|
const index = (y * width + x) * 4;
|
||||||
// Green (0%) -> Yellow (50%) -> Red (100%)
|
data[index] = r;
|
||||||
// Hue: 120 -> 0
|
data[index + 1] = g;
|
||||||
const hue = 120 * (1 - value / 100);
|
data[index + 2] = b;
|
||||||
|
data[index + 3] = 255; // Alpha
|
||||||
// Convert HSL to RGB (Simplified)
|
}
|
||||||
// Saturation 100%, Lightness 50%
|
}
|
||||||
const [r, g, b] = hslToRgb(hue / 360, 1, 0.5);
|
ctx.putImageData(imgData, 0, 0);
|
||||||
|
cachedBackground.value = imgData;
|
||||||
const index = (y * width + x) * 4;
|
|
||||||
data[index] = r;
|
|
||||||
data[index + 1] = g;
|
|
||||||
data[index + 2] = b;
|
|
||||||
data[index + 3] = 255; // Alpha
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx.putImageData(imgData, 0, 0);
|
|
||||||
|
|
||||||
// Draw current position
|
// Draw current position
|
||||||
// Map current fillRate/size to x,y
|
// Map current fillRate/size to x,y
|
||||||
@@ -166,6 +163,8 @@ const showAdvanced = ref(false);
|
|||||||
const toggleAdvanced = () => {
|
const toggleAdvanced = () => {
|
||||||
showAdvanced.value = !showAdvanced.value;
|
showAdvanced.value = !showAdvanced.value;
|
||||||
if (showAdvanced.value) {
|
if (showAdvanced.value) {
|
||||||
|
// Reset cache when opening to ensure size is correct if canvas resized
|
||||||
|
cachedBackground.value = null;
|
||||||
nextTick(drawMap);
|
nextTick(drawMap);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user