Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

Плавная смена (Анимация) Svg Path D координат

#javascript #html #jquery #анимация #svg


Здравствуйте!

Есть svg path с координатами: 

M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 z M 19,14 L 19,22 C 20.48,21.32
21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 z M 19,11.29 C 21.89,12.15 24,14.83
24,18 C 24,21.17 21.89,23.85 19,24.71 L 19,26.77 C 23.01,25.86 26,22.28 26,18 C 26,13.72
23.01,10.14 19,9.23 L 19,11.29 z


Как можно сделать, что бы координаты в svg path плавно изменились на эти при нажатии:

M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 Z M 19,14 L 19,22 C 20.48,21.32
21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 Z


Заранее спасибо.
    


Ответы

Ответ 1



Решение данной проблемы с помощью JQuery: $.prototype.animatePathD = function(d, o) { // Подстраиваем под разные браузера var i = $('body *').length; $('body').append(''); d = $('#animatepathd' + i + ' path').attr('d'); $('#animatepathd' + i).remove(); var e = this, d = { primary: { frame: $(e).attr('d').replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'), coord: $(e).attr('d').replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',') }, final: { frame: d.replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'), coord: d.replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',') } }, opt = o; if (opt == undefined) { opt = { duration: 1000, easing: 'linear' }; } else if (/^\d+$/.exec(opt) != null) { opt = { duration: opt, easing: 'linear' }; if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) { opt.duration = 1000 }; } else { if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) { opt.duration = 1000 }; if (opt.easing != 'swing' && opt.easing != 'linear') { opt.easing = 'linear' }; }; if (d.primary.frame == d.final.frame) { var funPoint = { primary: {}, final: {}, list: '', frame: "'" + d.final.frame + "'" }; for (var i = 0; i < d.primary.coord.length; i++) { funPoint.primary['c' + i] = d.primary.coord[i]; funPoint.final['c' + i] = d.final.coord[i]; funPoint.list = ', c' + i; if (d.primary.coord.length != 0) { funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+obj.elem.c" + i + "+'") } else { funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+c" + i + "+'") }; }; funPoint.list = funPoint.list.replace(/^\,\ (.+)$/, '$1'); $(funPoint.primary).animate(funPoint.final, { duration: opt.duration, easing: opt.easing, step: function(c0, obj) { $(e).attr('d', eval(funPoint.frame)); } }); } else { console.error('Frameworks coordinates do not match!'); }; }; Запускается он таким образом: $(svg path).animatePathD('coordinates', opt); coordinates - новые координаты; opt - скорость выполнения анимации или параметры выполнения. Принимает всего 2 параметра: duration (скорость выполнения; принимает только числа; по умолчанию - 1000) и easing (вид анимации; принимает два параметра: linear и swing; по умолчанию - linear); Пример на внешнем редакторе: https://jsfiddle.net/yuri_spivak/ws4xknot/ Пример на сайте: $.prototype.animatePathD = function(d, o) { // Подстраиваем под разные браузера var i = $('body *').length; $('body').append(''); d = $('#animatepathd' + i + ' path').attr('d'); $('#animatepathd' + i).remove(); var e = this, d = { primary: { frame: $(e).attr('d').replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'), coord: $(e).attr('d').replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',') }, final: { frame: d.replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'), coord: d.replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',') } }, opt = o; if (opt == undefined) { opt = { duration: 1000, easing: 'linear' }; } else if (/^\d+$/.exec(opt) != null) { opt = { duration: opt, easing: 'linear' }; if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) { opt.duration = 1000 }; } else { if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) { opt.duration = 1000 }; if (opt.easing != 'swing' && opt.easing != 'linear') { opt.easing = 'linear' }; }; if (d.primary.frame == d.final.frame) { var funPoint = { primary: {}, final: {}, list: '', frame: "'" + d.final.frame + "'" }; for (var i = 0; i < d.primary.coord.length; i++) { funPoint.primary['c' + i] = d.primary.coord[i]; funPoint.final['c' + i] = d.final.coord[i]; funPoint.list = ', c' + i; if (d.primary.coord.length != 0) { funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+obj.elem.c" + i + "+'") } else { funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+c" + i + "+'") }; }; funPoint.list = funPoint.list.replace(/^\,\ (.+)$/, '$1'); $(funPoint.primary).animate(funPoint.final, { duration: opt.duration, easing: opt.easing, step: function(c0, obj) { $(e).attr('d', eval(funPoint.frame)); } }); } else { console.error('Frameworks coordinates do not match!'); }; }; $(function() { $('#button').click(function() { if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) { $('#button svg path').animatePathD('M 12,26 16,26 16,10 12,10 z M 21,26 25,26 25,10 21,10 z', { duration: 150, easing: 'linear' }); $('#button').removeClass('-pause'); $('#button').addClass('-play'); } else { $('#button svg path').animatePathD('M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z', 150); $('#button').removeClass('-play'); $('#button').addClass('-pause'); }; return false; }); }); @import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }'); #button { min-width: auto; padding: 3px 3px 0 1px; cursor: pointer; }

Ответ 2



Решение с использованием анимаций SVG: Для этого нам понадобится создать в path две анимации с нужными координатами и при нажатии на кнопку скриптом запускать одну из анимаций Пример на сайте: $(function() { $('#button').click(function() { if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) { $('#button svg path .button-play')[0].beginElement(); $('#button').removeClass('-pause'); $('#button').addClass('-play'); } else { $('#button svg path .button-pause')[0].beginElement(); $('#button').removeClass('-play'); $('#button').addClass('-pause'); }; return false; }); }); @import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }'); #button { min-width: auto; padding: 3px 3px 0 1px; cursor: pointer; }

Ответ 3



Вариант скрипта с использованием стандартной анимации svg: $.prototype.animatePathD = function(d) { var e = this, animate = $(e).find('animate[data-animatePathD]'); if(animate.length){ animate.attr({ 'attributeName': 'd', 'attributeType': 'XML', 'from': animate.attr('to') || $(e).attr('d'), 'to': d, 'fill': 'freeze' }); animate[0].beginElement(); }; }; Запуск: Добавляем в path элемент animate с атрибутом data-animatePathD и всеми нужными свойствами Пример: В функции JS меняем координаты функцией: $(svg path).animatePathD('coordinates'); svg path - путь к элементу path; coordinates - новые координаты; Пример на сайте: $.prototype.animatePathD = function(d) { var e = this, animate = $(e).find('animate[data-animatePathD]'); if(animate.length){ animate.attr({ 'attributeName': 'd', 'attributeType': 'XML', 'from': animate.attr('to') || $(e).attr('d'), 'to': d, 'fill': 'freeze' }); animate[0].beginElement(); }; }; $(function() { $('#button').click(function() { if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) { $('#button svg path').animatePathD('M 12,26 16,26 16,10 12,10 z M 21,26 25,26 25,10 21,10 z'); $('#button').removeClass('-pause'); $('#button').addClass('-play'); } else { $('#button svg path').animatePathD('M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z'); $('#button').removeClass('-play'); $('#button').addClass('-pause'); }; return false; }); }); @import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }'); #button { min-width: auto; padding: 3px 3px 0 1px; cursor: pointer; }

Комментариев нет:

Отправить комментарий