Недавно у автора появилось требование. Содержание требования: вокруг кольца отображается группа текста. Пользователь может добавлять текст. Каждому слову соответствует маленькая синяя точка вокруг кольца. Наведите указатель мыши на маленькую синюю точку над кольцом, которая излучает треугольник, а затем отображает текст. Давайте сначала посмотрим на эффект анимации!
Как показано на рисунке выше, когда указатель мыши наводится на соответствующую маленькую синюю точку, должен излучаться треугольный луч, а соответствующий текст отображается за пределами треугольника, а маленькая синяя точка становится маленькой белой точкой.
Когда пользователь вводит контент выше, контент добавляется по кольцу ниже. Как показано на картинке выше.
Первоначальная идея автора заключалась в том, чтобы реализовать его с помощью CSS, точно так же, как динамическое вторичное меню на рисунке ниже.
Однако, учитывая, что содержимое на краю кольца является переменным и его необходимо расположить вокруг кольца, реализовать CSS может быть сложно. Ух ты, автор решил использовать холст, чтобы добиться этого. (Автор только недавно освоил холст. Если что-то не так, принимаю ваши поправки).
Процесс реализации:первый:
HTML-часть кода выглядит следующим образом:
<canvas style=margin-left: 50px;padding-top: 20px; display:block; id=canvas > Текущая версия вашего браузера не поддерживает холст</canvas>
Конкретные этапы реализации следующие:
1. Нарисуйте большой круг.
Используйте метод холста: context.arc(x, y, radius, startAngle, endAngle [, против часовой стрелки]);
x, y: координаты центра окружности, radius: радиус центра окружности, startAngle: рисование начального радиана, endAngle: рисование конечного радиана, [, против часовой стрелки]: необязательный параметр, следует ли рисовать дугу по часовой стрелке или против часовой стрелки.
Для удобства рисования автор переместил начало холста из предыдущего верхнего левого угла в центр холста.
Радиус кольца, рассчитанный автором, составляет r-80.
Canvas.width = 500canvas.height = 500 // Вычисляем радиус центра холста, пусть r = 500 / 2 // Перемещаем начало координат холста в центр холста при инициализации интерфейса ctx.translate(r ,r) //Перемещаем кисть в закругленное положение
Конкретный код выглядит следующим образом:
//Инициализация холста let Canvas = document.getElementById('canvas')let ctx= Canvas.getContext('2d')let Ratio = getPixelRato(ctx)canvas.width = 500canvas.height = 500 //Вычисляем радиус центра холста let r = 500 / 2// Когда интерфейс инициализируется, переместите начало координат холста в центр холста ctx.translate(r,r) //Перемещаем кисть к кругу ctx.lineWidth = 3; //Устанавливаем ширину линии кисти ctx.beginPath() //Запускаем кисть//Нарисуем цвет градиента края круга var arcColor = ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .strokeStyle= arcColor;//Установим цвет кисти ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Рисуем круг, координаты 0,0, радиус 250-80, полный круг (0–360 градусов), false означает движение по часовой стрелке ctx.closePath()ctx.stroke() //РисованиеРезультаты розыгрыша следующие.
2. Нарисуйте фоновое изображение в середине кольца (начало текущего холста — центр холста).
drawImage(изображение, dx, dy, dWidth, dHeight)
изображение: ресурс изображения Canvas, например изображение <img>, изображение SVG, сам элемент Canvas и т. д.
dx, dy: спланируйте область на холсте для размещения изображений. dx — это горизонтальные и вертикальные координаты верхнего левого угла этой области.
dWidth, dHeight: запланируйте область на холсте Canvas для размещения изображений, ширину и высоту этой области.
Следующие координаты рассчитаны автором
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Перемещаем начало координат в центр ctx.drawImage(image,-140,-140,280,280)}Результаты розыгрыша следующие:
3. Нарисуйте на кольце текст и маленькие точки (начало текущего холста — центр холста)
Рисование целей для текста и маленьких точек:
3.1 Маленькие точки равномерно отображаются на большом кольце
3.2 Текст немного разбросан за пределами мелких точек
Решение:1. Автор использует массив для хранения текущих слов.
let textArr = ['Широкое море и небо','Технические возможности','Большие средства','Контроль технического обслуживания','Живите и работайте в мире и довольстве','Наблюдайте за цветами','Завершите последние штрихи',' Избавься от хлама», «Иди против ветра», «Карьерный рост»
2. Поскольку количество маленьких точек и количество слов одинаково, количество их обоих равно длине массива textArr, приведенного выше.
3. Радиан полного круга равен 2π. Чтобы маленькие точки делили кольцо поровну, автор сначала вычисляет радиан точки, в которой расположена каждая маленькая точка.
for(let i = 0;i<lengths;i++){ // Вычисляем радианы let rad = 2*Math.PI/lengths*i}4. С помощью тригонометрических функций можно вычислить координаты (x, y) текущей маленькой точки на холсте (начало текущего холста — центр холста)
Среди них взаимосвязь между радианом, маленькой точкой, кольцом, радиусом кольца и началом полотна, для их описания автор нарисовал картинку.
Вычисляем координаты текста:
// Вычисляем координаты центра маленького круга let x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
Вычислите координаты маленькой точки: поскольку центр маленькой точки должен приходиться на кольцо, рассчитанные горизонтальные и вертикальные координаты будут следующими:
// Вычисляем координаты текста let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)
Конкретный код выглядит следующим образом:
// Рисуем текст ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //радианы let rad = 2*Math.PI/lengths*i // Вычисляем координаты центра маленького круга let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Рисуем маленькие точки for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Рисуем маленькие серые полупрозрачные точки на краю ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0.8)' ctx.arc(x,y,8,0,2*Math.PI,false) ctx.closePath() ctx.fill() // Рисуем маленькие синие точки ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath() ctx .наполнять() }Результаты розыгрыша следующие:
4. Нарисуйте треугольник снаружи каждой маленькой точки (начало текущего холста — центр холста).
4.1 Поскольку вы хотите нарисовать фигуру треугольника, идея рисования треугольника состоит в том, чтобы нарисовать линии с обеих сторон с центром текущей маленькой точки в качестве отправной точки, затем использовать ctx.fill(), чтобы закрыть фигуру и заполните интерьер градиентным цветом.
Нарисуйте треугольник: координаты вычисляются сами собой. Автор складывает и вычитает 35 по оси абсцисс и 70 по ординате (как хотите, ха-ха-ха)
//Запускаем кисть ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Нарисуйте текст под треугольником: (Чтобы отличить его от предыдущего текста, я использовал здесь красный текст)
ctx.fillStyle = '#e3211c' ctx.fillText(textArr[i],x,y+75)
Конкретный код выглядит следующим образом:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // // Рисуем треугольник // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Запускаем кисть ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Устанавливаем цветовой градиент- — ->Добавить цвет от центра к обеим сторонам var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)}Результаты розыгрыша следующие:
4.2 Требование состоит в том, чтобы направление каждого треугольника было направлено наружу, а теперь направление треугольников — вниз, поэтому теперь вам нужно использовать метод вращения холста.
ctx.save() ctx.translate(x,y) // Угол поворота центрируется по каждой маленькой точке ctx.rotate( rad - Math.PI/2 ) // Потому что маленькая точка ctx.translate(- x, - y) Опустите код рисования треугольников и текста.
Из расчета видно, что если принять центр маленькой точки за начальную точку вращения, то дуга вращения треугольника должна быть дугой текущей маленькой точки минус π/2, поскольку начальная позиция вращения всегда начинается с положительного направления оси координат x, то есть начинается с 0 радиан, но теперь все треугольники имеют точку π/2 радиан, поэтому:
Радиан вращения = Радиан маленькой точки - π/2
Не забудьте использовать метод сохранения состояния Canvas() при вращении.
Restoration() поочередно извлекает сохраненное состояние Canvas из вершины стека. Если сохраненного состояния Canvas нет, при выполнении этого метода изменений не произойдет.
Обязательно не забудьте в конце использовать метод restart(). На этом этапе автор прослезился от сожаления. . .
Конкретный код:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // Рисуем треугольник s ctx.save() // Угол поворота центрируется по каждой маленькой точке, потому что маленькие точки находятся в начале ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Запуск кисти ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.closePath() //Установка градиента цвета --->Добавление переменной цвета от центра к обеим сторонам sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}Постройте результат:
Присмотритесь, что? ? ? Некоторый текст перевернут из-за проблем с вращением. Согласно наблюдениям, когда радиан больше π, текст становится перевернутым.
Пришло время написать волну суждений «если». . . .
Как повернуть текст:
function RotateContext(ctx, x, y, Degree) { // Поворот текста ctx.translate(x, y) // ctx.rotate(grade * Math.PI / 180) ctx.rotate(grade) ctx.translate(-x , -у) }Определите маленькие точки, радианы которых больше π.
if (rad > Math.PI) { // Поскольку текст должен отображаться на краю треугольника, текст должен вращаться вместе с треугольником, чтобы его всегда можно было // удерживать на краю треугольника. После вращения. , текст появится, когда радиан больше π. Реверс проблемы: поверните текст ctx.save() ctx.beginPath() // Поворот текста RotateContext(ctx, x, y+75, Math.PI) ctx.font = 'Arial 13 пикселей' ctx.textAlign = 'center' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i) ], х, у + 75)}Результаты розыгрыша следующие:
С нетерпением ждем победы, мы почти добились успеха. По крайней мере, у нас есть приблизительный план. Революция еще не удалась, и товарищам еще нужно много работать! !
5. Ниже приводится реализация: когда указатель мыши находится над маленькой точкой, отображается треугольник на краю и текст на краю треугольника, но текст на краю круга не отображается.
Идея:1. Привяжите событие ввода мыши к холсту.
2. Определите, равны ли координаты текущего положения мыши на холсте координатам возле маленькой точки. Если да, отобразите треугольник, соответствующий маленькой точке.
5.1 Привязываем событие mousemove к холсту: мышь находится над событием
Canvas.addEventListener('mousemove',clickEvent)5.2 Рассчитать текущие координаты мыши на холсте
Метод расчета: используйте текущие координаты мыши в DOM, чтобы вычесть расстояние от левой или верхней части холста, чтобы рассчитать расстояние до холста.
Метод drawOne на рисунке ниже — это метод рисования, который будет обсуждаться далее в статье.
function clickEvent() { // Координаты положения мыши let x = event.clientX - Canvas.getBoundingClientRect().left let y = event.clientY - Canvas.getBoundingClientRect().top drawOne(x,y)}5.3, поскольку координаты мыши на холсте, вычисленные выше, рассчитываются с использованием верхнего левого угла холста в качестве начала координат, но начало координат текущего холста уже переместилось в центр холста (250,250), поэтому при использовании чтобы определить, является ли щелчок маленькими точками Вам нужно вычесть 250 из горизонтальной и вертикальной координат, чтобы сравнить их с координатами маленькой точки на текущем холсте. Когда я выносил решение, я обнаружил проблему, не знаю, почему разница в направлении y. автора — 260 вместо 250. Итак, автор вычитал 260 по направлению y.
Код выглядит следующим образом:
Среди них Cx, Cy — координаты мыши на холсте (левый верхний угол холста — начало координат), x, y — координаты текущей маленькой точки,
Автор напрямую рассчитал положение 15 пикселей возле центра маленькой точки, и все треугольники отобразились, а маленькая точка стала белой.
Самое главное, что вам нужно очищать предыдущий холст каждый раз, когда вы перерисовываете: не забудьте использовать метод ClearRect для очистки холста.
let XX = Cx - 250let YY = Cy- 260let leftX = x - 15 let rightX = x + 15let topY = y - 15let lowY = y + 15if (XX >= leftX && XX <= rightX && YY <= BottomY && YY > = topY ) {// Нажимается. . . . . . //Напишите код рисования посередине}За кодом следует ссылка:
6. Определите вход в интерфейсе и привяжите событие изменения к входу.
Реализация: интерфейс перерисовывается каждый раз, когда изменяется значение входных данных.
HTML-код:
<input type=text id=inpt style=margin-left: 100px;margin-top: 50px заполнитель=Пожалуйста, введите...>
js-код:
let inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //Это Метод - метод рисования, исходный код будет приведен далее в статье}})7. Есть проблема. Каждый раз при нажатии на интерфейс и перерисовке интерфейса будет мигать ситуация.
Как показано ниже:
Каждый раз при скольжении, поскольку координаты мыши меняются, необходимо очищать содержимое вокруг кольца и перерисовывать его. Поэтому вам нужно очистить холст, чтобы добиться динамических эффектов.
ClearRect() очень часто используется при рисовании анимации Canvas. Он постоянно очищает содержимое холста, а затем рисует его для формирования эффекта анимации.
ClearRect() может сделать прямоугольную область на холсте элемента Canvas прозрачной.
context.clearRect(x, y, ширина, высота);
x, y: координаты x, y верхнего левого угла прямоугольника.
ширина, высота: ширина и высота очищаемой прямоугольной области.
Поскольку ClearRect() может очищать только прямоугольную область холста, каждый раз, когда она очищается, фоновое изображение в середине будет очищаться вместе.
Поэтому фоновое изображение необходимо каждый раз перезагружать, а загрузка изображения занимает определенное время, поэтому оно будет мигать каждый раз, когда появляется.
Решение:drawImage(изображение, dx, dy, dWidth, dHeight)
Параметр image: ресурс изображения Canvas, например изображение <img>, изображение SVG, сам элемент Canvas и т. д.
Затем вы можете использовать другой холст для кэширования изображений.
Используйте дополнительный холст для рисования фонового изображения, но для этого холста, который не отображается в интерфейсе: display:none, а затем используйте его для очистки холста и прямой визуализации кэшированного объекта холста в середине отображаемого холста, что То есть нет необходимости загружать изображения один раз. Это отнимает много времени.
HTML-код:
<canvas width=280 height=280 style=margin-left: 50px;padding-top: 20px; display:none; id=canvas2> </canvas>
js-код:
//Используем кеширование для решения проблемы перерисовки перерисованных изображений var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; tempCanvas.height = 280let image = new Image( )image.src = 'image/quan.png'image.onload = () => { // Начало координат перемещается в центр tempCtx.drawImage(image,0,0,280,280)}После очистки холста нарисуйте кэшированный холст:tempCanvas непосредственно при перерисовке изображения.
// Рисуем кэшированный холст непосредственно в интерфейсе (интерфейс промежуточной шины кэшируется) ctx.drawImage(tempCanvas,-140,-140)
Хорошо, мне удалось, вот результат:
Адрес исходного кода следующий:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
Подвести итогВышеупомянутое представляет собой введение редактора в использование холста HTML5 для рисования анимации колец. Надеюсь, это будет вам полезно. Если у вас есть какие-либо вопросы, оставьте мне сообщение, и редактор ответит вам вовремя. Я также хотел бы поблагодарить всех за поддержку сайта боевых искусств VeVb!