SVG是矢量图形表示,它的一个强大之处在于path标签可以表示任意的矢量形状,利用好这个path可以做出很多传统html/css做不出来的效果。 Вот несколько примеров.
1. Сделайте анимацию пути
это я вSVG навигация подчеркивания курсора следует за эффектом"После статьи эта реализация дополняется, и итоговый эффект таков:
Код реализации выглядит следующим образом:
Анимация, созданная animateMotion в сочетании с путем, подробное описание можно увидеть выше.
2. Используйте клики неправильной формы
Как показано на рисунке ниже, необходимо добиться эффекта входа на какой континент при нажатии, например, при нажатии на Африку вы войдете в Африку:
Мы можем использовать div, чтобы установить рамку для охвата Африки, но если мы используем div, это может быть только обычный квадрат.Нет возможности ввести африканский континент, но контур континента неправильный, поэтому мы используем традиционный html не может решить эту проблему. Но использование пути SVG может решить эту проблему.Метод 1 заключается в прослушивании события щелчка пути, как показано на следующем рисунке:
Поскольку этот план можно получить из пользовательского интерфейса, они обычно рисуются с помощью векторного программного обеспечения, такого как AI / PS, и вы можете просто позволить им направить вам SVG.
Метод 2 заключается в вызове isPointInFill API SVG, чтобы определить, находится ли щелкнутая точка в области заполнения пути, Этого также можно добиться, но это более проблематично, чем метод 1, потому что положение мыши должно быть преобразуется в положение представления svg. .
3. Взаимодействие перетаскивания по пути
В первой точке по пути процесс анимации происходит автоматически, нет возможности позволить пользователям перетаскивать его в прошлое, чтобы добиться следующих результатов:
Этот тип сцены имеет регулятор громкости и т. д., которые должны иметь процентное управление. Вы можете использовать один первыйОнлайн-инструменты для SVGНарисуйте такой график:
Вы можете получить код SVG:
<svg class="volumn-controller" width="580" height="400" xmlns="http://www.w3.org/2000/svg">
<path class="volumn-path" stroke="#000" d="m100,247c93,-128 284,-129 388,6" opacity="0.5" stroke-width="1" fill="#fff"/>
<circle class="drag-button" r="12" cy="247" cx="100" stroke-width="1" stroke="#000" fill="#fff"/>
</g>
</svg>
Ключевым здесь является атрибут d в теге пути, d — это аббревиатура данных, которая определяет форму пути, и многие атрибуты могут использоваться для управления изменением формы, как показано на следующем рисунке:
Чтобы добиться этого взаимодействия, необходимо динамически менять положение центра окружности (cx, cy) на соответствующее место на пути. SVG не предоставляет связанный API напрямую, но предоставляет API с именем getPointAtLength, который можно использовать косвенно, передавая параметр длины, как показано в следующем коде:
let volumnPath = document.querySelector('.volumn-path');
// 输出path在长度为100的位置的点坐标
console.log(volumnPath.getPointAtLength(100));
// 输出当前path的总长度
console.log(volumnPath.getTotalLength());
Вывод консоли:
Измените cx/cy круга на вышеуказанные координаты x/y, и круг переместится в соответствующее положение:
Проблема здесь в том, что параметр длины, передаваемый этим API, относится к длине кривой, но положение движения мыши является линейным, и нет способа напрямую узнать, как далеко текущая мышь находится на кривой от точки. Начальная позиция.
Итак, нам нужно рассчитать, в этой сцене мы можем взять положение координаты x мыши на кривой, как показано на следующем рисунке:
На данный момент есть идея: вы можете вычислить длину каждого второго пикселя на этом пути, чтобы узнать, где находятся его координаты, а затем сохранить это в массиве. Поскольку координата x известна при движении мыши, вы можете проверить координату y соответствующей координаты x в этом массиве, и вы можете получить желаемый центр круга.
Поэтому сначала выполните вычисления и сохраните в массив:
let $volumnController = document.querySelector('.volumn-controller'),
$volumnPath = $volumnController.querySelector('.volumn-path');
// 得到当前路径的总长度
let pathTotalLength = $volumnPath.getTotalLength() >> 0;
let points = [];
// 起始位置为长度为0的位置
let startX = Math.round($volumnPath.getPointAtLength(0).x);
// 每隔一个像素距离就保存一下路径上点的坐标
for (let i = 0; i < pathTotalLength; i++) {
let p = $volumnPath.getPointAtLength(i);
// 保存的坐标用四舍五入,可以平衡误差
points[Math.round(p.x) - startX] = Math.round(p.y);
}
Здесь для его сохранения используется массив p0ints, а его индексный индекс — это координата x, а значение — координата y. В этом примере общая длина составляет 451,5 пикселя, а длина результирующего массива точек — 388. Вы можете сохранять координаты каждые 0,5 пикселя, но в этом примере достаточно 1 пикселя.
Затем прослушивайте события мыши, получайте координату x, запрашивайте координату y и динамически меняйте центр круга, как показано в следующем коде:
let $dragButton = $volumnController.querySelector('.drag-button'),
// 得到起始位置相对当前视窗的位置,相当于jQuery.fn.offset
dragButtonPos = $dragButton.getBoundingClientRect();
function movePoint (event) {
// 当前鼠标的位置减去圆心起始位置就得到移位偏差,12是半径值,这里先直接写死
let diffX = event.clientX - Math.round(dragButtonPos.left + 12);
// 需要做个边界判断
diffX < 0 && (diffX = 0);
diffX >= points.length && (diffX = points.length - 1);
// startX是在上面的代码得到的长度为0的位置
$dragButton.setAttribute('cx', diffX + startX);
// 使用points数组得到y坐标
$dragButton.setAttribute('cy', points[diffX]);
}
$dragButton.addEventListener('mousedown', function (event) {
document.addEventListener('mousemove', movePoint);
});
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', movePoint);
});
Код этой реализации также относительно прост.То, на что следует обратить внимание, это выбор начальной позиции.Есть две системы координат, одна относительно окна страницы, и ее исходная (0, 0) координатная точка — это видимая область текущей страницы (клиентский) верхний левый угол, вторая система координат — это система координат SVG, а его исходная (0, 0) позиция — это верхний левый угол холста SVG, как показано на следующий рисунок:
Положение мыши относительно клиента просмотра, поэтому вам нужно получить положение круга в клиенте, которое можно получить через нативный getBoundingClient, а затем вычесть clientX круга из clientX мыши в получить правильное отклонение смещения diff.Это значение diff добавляется к Круг может получить координату x в svg в начальной позиции координаты svg, затем проверить массив точек, чтобы получить координату y, а затем установить cx/cy значение круга.
Реализация этого уже очень проста, около 30 строк кода. Следует отметить, что если svg масштабируется, координаты также должны быть изменены пропорционально. Так что лучше не масштабировать, отображение 1:1 гораздо проще.
Что делать, если вы хотите отобразить определенное значение громкости? Это легко сделать, просто сохраните длину пути при сохранении координат точки на первом шаге, окончательный эффект будет следующим:
Полная демонстрация:svg-path-drag.html
Что, если путь сложный, координата x может соответствовать двум точкам, как показано на следующем рисунке:
Также есть способ сделать это, метод расчета аналогичен, также необходимо вынести все координаты каждой точки 1px на пути, а затем вычислить положение мыши, которое ближе всего к координатам точки , а затем просто возьмите эту точку. Конечно, при определении оптимальной точки алгоритм необходимо оптимизировать, а цикл for нельзя использовать напрямую, подробнее см.codepen.
4. Анимация деформации пути
Пути в сочетании с ключевыми кадрами могут создавать некоторые интересные эффекты, такие как этотcodepenПример:
Его реализация состоит в том, чтобы изменить значение d пути при наведении курсора, а затем выполнить анимацию перехода d следующим образом:
<svg viewBox="0 0 10 10" class="svg-1">
<path d="M2,2 L8,8" />
</svg>
<style>
.svg-1:hover path {
d: path("M8,2 L2,8");
}
path {
transition: d 0.5s linear;
}
</style>
Эта анимация перехода деформации является условной, то есть ее формат данных пути должен быть согласованным, и количество атрибутов M/L/C должно быть согласованным, иначе анимация деформации не может быть выполнена.
5. Объедините clip-path для эффекта маски
Используя CSS, вы обычно можете использовать только радиус границы для создания некоторых закругленных масок, то есть радиус границы в сочетании с переполнением: скрыто, но с помощью пути клипа + пути svg можно создавать маски любой формы, как показано ниже, чтобы сделать сердце форма:
Как показано в следующем коде:
<div style="width:200px;height:200px">
<img src="photo.png" alt style="width:100%">
</div>
<style>
img {
clip-path: url("#heart");
}
</style>
Идентификатор: #heart в стиле — это clipPath, указывающий на SVG, как показано на следующем рисунке:
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<clipPath id="heart" clipPathUnits="objectBoundingBox">
<path transform="scale(0.0081967, 0.0101010)" d="m61.18795,24.08746c24.91828,-57.29309 122.5489,0 0,73.66254c-122.5489,-73.66254 -24.91828,-130.95562 0,-73.66254z"/>
</clipPath>
</svg>
Чтобы этого пути было достаточно для размещения 100% ширины контейнера div, вам нужно установить:
clipPathUnits="objectBoundingBox"
Это приведет к тому, что единица в атрибуте d станет шкалой от 0 до 1, поэтому ее необходимо уменьшить. Исходная ширина равна 122, а высота — 99. Значение шкалы должно быть (1/122, 1 / 99). Это позволит достичь цели 100% заполнения.Если соотношение координат атрибута d в начале равно 0 к 1, в этом нет необходимости.
Кроме того, clip-path использует путь svg и не поддерживает анимацию деформации.
В этой статье представлены несколько эффектов с использованием пути svg: создание анимации пути, нажатие на неправильные формы, перетаскивание вдоль пути, анимация деформации пути и выполнение некоторых эффектов маскирования с помощью clip-path. Можно сказать, что эффект пути svg по-прежнему очень силен.Когда у вас есть некоторые эффекты, которых нельзя достичь с помощью html/css, вы можете подумать в направлении svg.
【Дополнительный】"Эффективный интерфейс》Напечатано во второй раз, я слышал, что вы еще не купили