function markTransition({key,selector,attributes,duration}) {
let currentStateMap = null;
function renderWrapper(target) {
return function render(...args) {
let rootElement = target.render(...args);
let lastStateMap = currentStateMap;
let data = target.data;
currentStateMap = new Map();
d3.select(rootElement)
.selectAll(selector)
.each(function(d){
let attr = {};
for(let attrName of attributes) {
attr[attrName] = d3.select(this).attr(attrName)
}
currentStateMap.set(key(data[d]),attr);
})
.each(function(d){
let attrs = lastStateMap?.get(key(data[d]));
if(attrs) {
for(let attrName in attrs) {
d3.select(this).attr(attrName,attrs[attrName]);
}
}
})
.transition()
.duration(duration)
.call(s => {
attributes.forEach(attrName => {
s.attr(attrName,d=>currentStateMap.get(key(data[d]))[attrName]);
})
})
;
return rootElement;
}
}
return function(mark) {
return new Proxy(mark,{get:(target, name)=>name==="render"?renderWrapper(target):target[name]});
}
}