Другим вариантом, если производительность является проблемой, является использование расширения data.table
для расширения reshape2
расплава & amp; dcast functions
( Ссылка: эффективная перестройка с использованием data.tables )
library(data.table)
setDT(dat1)
dcast(dat1, name ~ numbers, value.var = "value")
# name 1 2 3 4
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814
И, как и в data.table v1.9.6, мы можем использовать несколько столбцов
## add an extra column
dat1[, value2 := value * 2]
## cast multiple value columns
dcast(dat1, name ~ numbers, value.var = c("value", "value2"))
# name value_1 value_2 value_3 value_4 value2_1 value2_2 value2_3 value2_4
# 1: firstName 0.1836433 -0.8356286 1.5952808 0.3295078 0.3672866 -1.6712572 3.190562 0.6590155
# 2: secondName -0.8204684 0.4874291 0.7383247 0.5757814 -1.6409368 0.9748581 1.476649 1.1515627
В D3 переход в основном интерполирует начальное значение к конечному значению. Это может быть легко продемонстрировать, если мы интерполируем числа. Например, давайте перейдем от 50
к 2000
:
const interpolator = d3.interpolate(50, 2000);
d3.range(0, 1.05, 0.05).forEach(function(d) {
console.log(interpolator(d))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Мы также можем интерполировать строки:
const interpolator = d3.interpolate("March, 2000", "March, 2020");
d3.range(0, 1.05, 0.05).forEach(function(d) {
console.log(interpolator(d))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Теперь давайте посмотрим на ваш случай: вы хотите интерполировать из этого:
url("#gradient-red")
К этому:
url("#gradient-blue")
[1130] Каковы возможные промежуточные звенья здесь? Вы видите, что это невозможно? Вот доказательство:
const interpolator = d3.interpolate("url(#gradient-red)", "url(#gradient-blue)");
d3.range(0, 1.1, 0.1).forEach(function(d) {
console.log(interpolator(d))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Как видите, самая первая интерполяция мгновенно приведет к концу значение. [тысяча сто сорок четыре]
Наиболее очевидным решением является интерполяция стоп-цвета. Однако, как вы только что обнаружили, это изменит градиент всех кругов.
Итак, наивное исправление создает несколько градиентов, по одному на каждый круг, с уникальными идентификаторами. Хотя это может быть подходящим решением для 3 или 4 кругов, это явно не умное решение, если у вас есть десятки или сотни элементов.
Это, как говорится, это мое предложение:
#gradient-temporary
, точно так же, как красный. [тысяча сто тридцать одна] "url(#gradient-red)"
на "url(#gradient-temporary)"
. Это изменение немедленно, никакого эффекта на экране не видно. "url(#gradient-temporary)"
на "url(#gradient-blue)"
. Опять же, это немедленно. Также измените цвет остановки временного градиента на красный. Таким образом, вы можете иметь сотни кругов, но вам просто нужно 3 градиента для их перехода.
Вот демонстрация с этим подходом, нажмите на каждый кружок, чтобы перевести его:
const circles = d3.selectAll("circle");
circles.on("click", function() {
const element = this;
d3.select(element).style("fill", "url(#gradient-temporary)");
d3.select("#gradient-temporary").select("stop:nth-child(2)")
.transition()
.duration(1000)
.style("stop-color", "rgb(0,0,255)")
.on("end", function() {
d3.select(element).style("fill", "url(#gradient-blue)");
d3.select("#gradient-temporary").select("stop:nth-child(2)")
.style("stop-color", "rgb(255,0,0)")
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<defs>
<linearGradient id="gradient-red" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(211,211,211);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="gradient-temporary" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(211,211,211);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="gradient-blue" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(211,211,211);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</linearGradient>
</defs>
<g class="node">
<circle r="20" cx="20" cy="70" style="fill: url('#gradient-red');"></circle>
</g>
<g class="node">
<circle r="20" cx="80" cy="70" style="fill: url('#gradient-red');"></circle>
</g>
<g class="node">
<circle r="20" cx="140" cy="70" style="fill: url('#gradient-red');"></circle>
</g>
<g class="node">
<circle r="20" cx="200" cy="70" style="fill: url('#gradient-red');"></circle>
</g>
<g class="node">
<circle r="20" cx="260" cy="70" style="fill: url('#gradient-red');"></circle>
</g>
</svg>