#svg #d3.js
#svg #d3.js
Вопрос:
Меня попросили создать панель инструментов для визуализации механических принципов катания на лыжах. Первое, что он хочет, чтобы я сделал, это визуализировать сопротивление воздуха, связанное с катанием на лыжах. Поэтому я думаю, было бы неплохо, если бы я мог создать значок SVG лыжника, который может двигаться в разных направлениях. Например, чтобы визуализировать эффект правильного положения рук при катании на лыжах, я хочу иметь возможность больше двигать руками перед лыжником, а не свисать вниз. Простая 2D графика.
В D3 нравится добавлять изображения, подобные этому.
const skier = g
.append('image')
.attr('id', 'skier')
.datum(p3)
.attr('href', skierIconSvg)
.attr('width', 100)
.attr('height', 100)
.attr('transform', 'translate(-50, -40)')
Но при таком подходе мне сложно просто выполнить анимацию только одного элемента (например, arm) на значке svg. Итак, мой вопрос в том, есть ли способ анимировать только один элемент внешнего значка svg в D3.js ?
Комментарии:
1. изображения не поддерживают сценарии, так что это будет практически невозможно.
2. Ого .. так что, невозможно нарисовать внешний значок svg, обернуть некоторые его элементы элементом g, а затем иметь возможность выполнять анимацию только для этих элементов g?
3. Как вы планируете «обернуть некоторые элементы» изображения. Изображение непрозрачное, вы не можете получить доступ к его содержимому.
4. bl.ocks.org/mbostock/1014829 — Я подумал, что мог бы добавить элемент g в svg, возможно, с именем класса, а затем использовать d3 для выбора только этого элемента 🙊
5. Который использует iframe, а не элемент изображения.
Ответ №1:
Это должно быть возможно, я создал эту демонстрацию о том, как это сделать. Я анализирую SVG как XML и добавляю его дочерние элементы непосредственно в мой доверенный XML-файл. Затем я могу выбрать arm и stick (у которых ужасные автоматически сгенерированные идентификаторы — вы можете изменить их внутри самого файла SVG) и повернуть их.
Единственное, что действительно раздражает, это то, что поворот сильно смещает элементы. Я исправил это с помощью transform-origin
, который я вручную — методом проб и ошибок — установил рядом с плечевым суставом. Таким образом, рука будет вращаться вокруг плеча, а не вокруг верхнего левого края SVG.
// The herokuapp is just a hack to make it work on SO, should be easier
// for you locally
d3.xml('https://cors-anywhere.herokuapp.com/https://cmagelssen.no/skier.svg')
.then((xml) => {
const svgEl = d3.select('#mySvg')
.append('g')
.attr('id', 'skier')
.node();
Array.from(xml.documentElement.children).forEach((el) => {
svgEl.appendChild(el);
});
const skierG = d3.select("#skier > g > g");
const skierArms = d3.select("#skier #ailpBmbkR")
// Trial an error, but if you get this close to the skier's shoulder,
// you don't have to do a transform and can easily vary rotation!
.style("transform-origin", "322px 244px")
.style("transform", "rotate(30deg)");
const skierStick = d3.select("#skier #c4PTA7jJrE")
// Same point as the skier arms!
.style("transform-origin", "322px 244px")
.style("transform", "rotate(30deg)");
})
.catch((e) => {
console.error(e);
})
.finally(() => {
console.log('done');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="mySvg" width="500" height="500"></svg>
Комментарии:
1. Ваши знания о D3.js это действительно потрясающе, Рубен. Вы предоставляете решение всех моих проблем. Как вы нашли arm в моем svg? Это просто идентификационный тег в svg?
2. Я просто использовал инспектор элементов, чтобы найти соответствующий элемент path, идентификаторы на самом деле не описательные
3. Но в принципе. Я могу нарисовать свой значок в Adobe illustrator, сохранить его в svg. Тогда я могу зайти внутрь svg и добавить идентификационные теги к рукам, ногам, голове, телу?
4. Я не совсем уверен, но теоретически вы можете сделать именно это
5. Я попробую в эти выходные. Я пришлю вам обновленную информацию о том, как это происходит.