AlgiViz 0.8.0 · Canvas / TypeScript
Пользовательские палитры canvas в AlgiViz 0.8.0
Автор: Grundy · Проверено: 19 октября 2026
Canvas не наследует цвета из CSS. Когда на стенде Grundyjs появились светлая и тёмная темы и выбор фона, визуализация алгоритма продолжала жить со своей палитрой. Сначала мы решили это отдельным renderer сайта, затем добавили переопределение цветов в AlgiViz 0.8.0 и убрали дублирующую отрисовку. Разберём проблему, изменение библиотеки и интеграцию с сохранением текущего кадра.
1. Двух тем оказалось недостаточно для палитры сайта
До версии 0.8.0 createArrayRenderer принимал только theme: light или dark. Светлая тема была полезна, но не позволяла согласовать canvas с произвольным фоном страницы, цветом текста и элементов. Изменение CSS-переменной само по себе не перерисовывает уже нарисованные пиксели. Нам понадобился единый источник цветов для CSS, примера алгоритма и сцены записи CanvasTake. Определение системной темы, сохранение выбора посетителя и запуск перерисовки при этом остаются задачами сайта.
2. Временное решение показало границу библиотеки
В AlgiViz уже были публичные arrayScene, createSceneProjector и createSceneRenderer. Через них сайт построил renderer со своими цветами, сохранив прежние шаги алгоритма и плеер. Решение работало, но дублировало геометрию столбцов, переходы, подписи и правила подсветки. Ради другой палитры не должно требоваться сопровождать вторую реализацию той же визуализации. Переиспользуемое изменение следовало внести в стандартный renderer массивов.
3. Переопределяем только нужные цвета
Установите @grundyjs/algiviz@0.8.0. Теперь импорт из /canvas принимает colors вместе с theme: переданные роли объединяются с выбранной встроенной темой. В примере настройки ниже обычные столбцы, активные элементы и отсортированная часть сохраняют цвета светлой темы. Пропущенные свойства и явно переданный undefined оставляют значение темы. Прежние вызовы, в которых задана только тема, и псевдоним createSortRenderer продолжают работать. Для частичной палитры экспортирован тип ArrayPaletteOverrides, для всех параметров — ArrayRendererOptions.
import { createArrayRenderer } from "@grundyjs/algiviz/canvas";
const renderer = createArrayRenderer({
theme: "light",
colors: {
background: "#eef4c7",
text: "#202438",
held: "#87431d",
},
});4. Разделяем роли вместо одного акцента для всего
В ArrayPalette шесть цветов: background — фон canvas, text — подписи, bar — обычные элементы, sorted — окончательные позиции, active — подсвеченные операции, held — выбранный ключ. Полная палитра ниже — пример, а не обязательное оформление. Состояния должны различаться, а пояснение к визуализации — соответствовать цветам. Зелёная отсортированная область не должна сливаться с активным сравнением при смене акцента сайта. AlgiViz не проверяет контраст автоматически и не генерирует доступную палитру за приложение.
import type { ArrayPalette } from "@grundyjs/algiviz/canvas";
const palette: ArrayPalette = {
background: "#f4f1fb",
text: "#202438",
bar: "#475569",
sorted: "#047857",
active: "#b45309",
held: "#7c3aed",
};5. Заменяем renderer, сохраняем текущий кадр
Renderer копирует палитру при создании. Последующее изменение исходного объекта colors не обновляет его цвета. Создайте новый renderer для новой темы и нарисуйте кадр, который уже хранится в представлении. Браузерный адаптер ниже принимает canvas с заранее настроенными размерами и начальный ArrayFrame из вашей временной шкалы. Следующие кадры передавайте в view.render(frame), а из переключателя темы вызывайте view.setPalette(theme, colors). Адаптер не создаёт и не перезапускает временную шкалу и не переводит её на нулевую позицию. Размеры canvas и обработка devicePixelRatio остаются в адаптере отображения приложения.
import { createArrayRenderer } from "@grundyjs/algiviz/canvas";
import type { ArrayPaletteOverrides, ArrayRendererOptions } from "@grundyjs/algiviz/canvas";
import type { ArrayFrame } from "@grundyjs/algiviz/array";
export function createPaletteView(canvas: HTMLCanvasElement, initialFrame: ArrayFrame) {
const context = canvas.getContext("2d");
if (!context) throw new Error("Canvas 2D is unavailable");
let currentFrame = initialFrame;
let renderer = createArrayRenderer({ theme: "light" });
const render = (frame: ArrayFrame) => {
currentFrame = frame;
renderer.render(context, frame);
};
render(initialFrame);
return {
render,
setPalette(theme: ArrayRendererOptions["theme"], colors: ArrayPaletteOverrides = {}) {
renderer = createArrayRenderer({ theme, colors });
render(currentFrame);
},
};
}6. На сайте остаётся только адаптер цветов
Стенд вычисляет светлые и тёмные токены для CSS и canvas. SortingPlayer передаёт эти цвета стандартному renderer AlgiViz; отдельная отрисовка сцены удалена. На сайте фон canvas называется canvasBackground, а в библиотеке — background, поэтому оставшийся адаптер только сопоставляет имена свойств. Цвета операций отделены от выбранного посетителем акцента. Пример записи CanvasTake читает те же токены, но рисует свою сцену: поддержка палитры в AlgiViz не настраивает другую библиотеку автоматически.
import type { ArrayPalette } from "@grundyjs/algiviz/canvas";
type SiteCanvasColors = {
canvasBackground: string;
text: string;
bar: string;
sorted: string;
active: string;
held: string;
};
function arrayPalette(colors: SiteCanvasColors): ArrayPalette {
return {
background: colors.canvasBackground,
text: colors.text,
bar: colors.bar,
sorted: colors.sorted,
active: colors.active,
held: colors.held,
};
}7. Проверяем состояния, геометрию и смену темы
На сайте проверены обе темы на кадрах start, compare и select, в том числе с выбранным ключом, повторами и отрицательным значением. Проверки охватывают фон, текст и все четыре роли элементов, сравнивают координаты отрисовки и подписи со стандартным renderer AlgiViz и подтверждают, что смена палитры не меняет кадр и снимки состояния. Проверки DPR также прошли. Для интеграции 0.8.0 прошли проверки алгоритмов, lint и production-сборка. Автоматические проверки не доказывают визуальную различимость любой пользовательской палитры. Дополнительно проверьте в браузере обе темы, остановленный кадр, воспроизведение и узкий экран. Перед выбором итоговой палитры оцените читаемость подписей и различимость цветов операций.
8. Что изменилось и что осталось приложению
В библиотеке появилась небольшая точка расширения, а не второй плеер или система тем конкретного сайта. Прежние вызовы сохраняют стандартные цвета. Сайт управляет выбором темы, его сохранением и перерисовкой; AlgiViz отвечает за стандартную отрисовку массива. Интеграция сейчас работает на минималистичном стенде: это не означает, что все страницы алгоритмов уже переведены на новую тему сайта. Дальше палитру можно подбирать в токенах, не копируя renderer массива заново.