Чтобы корректно масштабировать содержимое `<canvas>` на устройствах с высоким количеством точек на дюйм (DPI), нужно учесть, что `<canvas>` имеет два отдельных размера: один для CSS и другой для пикселей. Давайте разберем, как можно реализовать эту логику масштабирования, а также правильно реагировать на комбинацию `ctrl + колесо мыши`.
### Основные шаги для масштабирования содержимого `<canvas>`:
1. **Адаптация размера `<canvas>`**:
Убедитесь, что вы устанавливаете размеры `<canvas>` в пикселях в соответствии с фактическим размером канваса, умноженным на `devicePixelRatio`.
2. **Масштабирование содержимого**:
Когда вы отрисовываете на канвасе, вы должны учитывать примененный масштаб.
3. **Обработка события `wheel` для масштабирования**:
Обработайте событие `wheel`, если пользователь нажимает `ctrl`, чтобы увеличить или уменьшить масштаб.
Вот пример кода для реализации этого:
```jsx
import React, { useEffect, useRef, useState } from 'react';
const CustomCanvas = () => {
const canvasRef = useRef(null);
const [scale, setScale] = useState(1);
useEffect(() => {
const canvas = canvasRef.current;
const context = canvas.getContext('2d');
// Поддержка высокой плотности пикселей
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
// Установка размеров canvas
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
// Масштабирование контекста
context.setTransform(dpr * scale, 0, 0, dpr * scale, 0, 0);
// Пример отрисовки (например, рисуем квадрат)
context.clearRect(0, 0, canvas.width, canvas.height); // Очистить
context.fillStyle = 'blue';
context.fillRect(10, 10, 100, 100); // Размер квадрата не зависит от scale
}, [scale]); // Запустить обновление при изменении масштаба
const handleWheel = (event) => {
if (event.ctrlKey) {
event.preventDefault(); // Предотвращаем прокрутку страницы
const newScale = scale + (event.deltaY < 0 ? 0.1 : -0.1); // Увеличиваем или уменьшаем масштаб
setScale(Math.max(newScale, 0.1)); // Минимальный масштаб 0.1
}
};
return (
<canvas
ref={canvasRef}
onWheel={handleWheel}
style={{ border: '1px solid black', width: '500px', height: '500px' }} // Применяем размеры в CSS
/>
);
};
export default CustomCanvas;
```
### Объяснение:
- **devicePixelRatio**: Мы получаем значение `devicePixelRatio`, чтобы корректно установить размеры `<canvas>` в пикселях.
- **setTransform**: Мы устанавливаем трансформацию контекста, учитывая текущий масштаб. Это позволяет масштабировать все, что вы рисуете на канвасе.
- **Обработка `wheel`**: Мы отслеживаем событие `wheel`, и если нажата клавиша `ctrl`, изменяем состояние масштаба.
Этот код позволяет вам корректно обрабатывать масштабирование и обеспечивать корректное отображение содержимого на устройствах с высоким DPI. Если у вас есть дополнительные требования или сложности, не стесняйтесь задавать уточняющие вопросы!