Сократить код - дублированный код с добавлением изображений SVG - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть график svg с несколькими различными типами узлов, причем каждый тип имеет много разных узлов с разным назначением.

Продукты, сообщества, события, проекты, группы продуктов.

Я хочу установить фоновые изображения каждого узла.

Каждый отдельный узел каждой из этих групп имеет свой уникальный идентификатор.Тип и идентификатор этих узлов можно использовать для получения изображения из конечной точки для всех типов, кроме групп продуктов, изображения которых находятся в папке ресурсов.

Я пытаюсь вызвать изображения из 1. конечных точек и 2. из папки ресурсов.

Мои конечные точки представляют различные типы и имеют идентификаторы, проанализированные в:

https://tiktok.org/products/${node.id}/standard

https://tiktok.org/communities/${node.id}/standard

Мой текущий метод выполнения этого кажется Чрезвычайно неэффективным, и яя не должен дублировать код!Я «добавляю» svg-изображение и ID, затем я ссылаюсь на них для node.types и анализирую их ID, но это просто загрузка кода (вот два типа в качестве примера):

   .selectAll('circle.node')
    .data(this.nodes)
    .enter();
  //products
  circle
    .filter(node => node.type === EngagementType.Product)
    .append("pattern")
    .attr("id", d => `insightImage-${d.id}`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", d => `https://tiktok.org/products/${d.id}/standard`) (fake link)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice');
  //communities
  circle
    .filter(node => node.type === EngagementType.Community)
    .append("pattern")
    .attr("id", d => `insightImageCom-${d.id}`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", d => `https://tiktok.org/communities/${d.id}/standard`)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice');

ЗатемЯ заполняю круг атрибутом стиля, как показано ниже:

  circle
    .filter(node => node.depth !== 0 && node.type === EngagementType.Product)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node && (node.depth === 4 && !node.isExtraNode))
    .style('fill', d => `url(#insightImage-${d.id})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));
  circle
    .filter(node => node.depth !== 0 && node.type === EngagementType.Community)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node && (node.depth === 4 && !node.isExtraNode))
    .style('fill', d => `url(#insightImageCom-${d.id})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));

У меня есть аналогичный метод для изображений в папке активов, у меня есть куча images.svg, а затем сделать то же самое, что и выше длягруппа продуктов, но на самом деле их называют индивидуально, занимая МАССЫ пространства ...

, в этом случае я вызываю узлы через их ID, чтобы индивидуально назначить изображение из папки ресурсов:

      circle
    .filter(node => node.type === EngagementType.ProductGroup && node.id === 'a6qb000000003olAAA')
    .append("pattern")
    .attr("id", `insightImageInitiative`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", './assets/d3-icons/initiative.svg')
    .attr("x", 0.2)
    .attr("y", 0.2)
    .attr("width", 0.60)
    .attr("height", 0.60)
    .attr('preserveAspectRatio', 'xMidYMid slice');
  circle
    .filter(node => node.type === EngagementType.ProductGroup && node.id === 'a6qb000000003okAAA')
    .append("pattern")
    .attr("id", `insightImageIndustry`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", './assets/d3-icons/industry.svg')
    .attr("x", 0.2)
    .attr("y", 0.2)
    .attr("width", 0.60)
    .attr("height", 0.60)
    .attr('preserveAspectRatio', 'xMidYMid slice');

Я пытался просто использовать стиль (заливка), но у меня это не сработало бы !!

    .style('fill', d => `url('./assets/d3-icons/calendar.svg')`) 
    .style('fill', d => `url('https://tiktok.org/products/${d.id}/standard')`) 

ничего не появляется!

Несколько советов / справок о том, как по-разному устанавливать изображения ИЛИ какизбавиться от такого большого количества дубликатов было бы замечательно!

Я уверен, что есть более простой способ установить фоновые изображения, конечно, конечные точки отличаются, хотя.

спасибо, если вы можете помочь!

1 Ответ

0 голосов
/ 12 февраля 2019

Объект данных, который вы используете, может быть любым.Наиболее подходящий шаблон - подготовить его перед тем, как прикрепить его к выбору элементов, и таким образом, чтобы у вас уже было все необходимое.

В следующем примере определяется сопоставление структуры данных между типами иданные, которые отличаются в зависимости от категории.Это только пример, ядро ​​- это то, что происходит в функции .map(): вы добавляете одно или несколько свойств к своему объекту данных, чтобы у вас была связь между node.type и способом, которым вы должны написать свой шаблон как раз длякаждый узел.

Необходим аналогичный способ подключения из идентификаторов к изображениям папки ресурсов.

Немного странно, что вы определяете шаблон для каждого узла, но рисуете только кругесли node.depth !== 0 Но это вам понятно, используйте функцию фильтра только для определения неуровневых записей, для которых требуется отобразить кружок.

const details = new Map([
    [EngagementType.Product, { path: 'products', prefix: 'insightImage'} ],
    [EngagementType.Community, { path: 'comunities', prefix: 'insightImageCom'} ],
    // and so on...
]);

// enhance your data, each node is a shallow copy with extra properties
const renderingData = this.nodes.map(node => Object.assign({
    patternId: `${details.get(node.type).prefix}-${d.id}`,
    imageUrl: `https://tiktok.org/${details.get(node.type).path}/${d.id}/standard`,
    isLeaf: node.depth === 4 && !node.isExtraNode
}, node));

const circle = d3.selectAll('circle.node')
    .data(renderingData)
    .enter();

// now it is straight forward
circle
    .append("pattern")
    .attr("id", d => node.patternId)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0);
    .append("image")
    .attr("xlink:href", d => d.imageUrl)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice')
  // and now you filter for non-toplevel nodes
  .filter(node => node.depth !== 0)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node.isLeaf)
    .style('fill', d => `url(#${d.patternId})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...