Ошибка при объединении кода "двойного щелчка" со старой заменой d3 "перепривязка"
Я пытаюсь восстановить событие двойного щелчка, которое было представлено в предыдущих версиях D3 для метода 'node.on'. Мне нужно использовать его с d3.forceSimulation.
Заменяющий фрагмент события двойного щелчка, который я нашел, прекрасно работает на старой версии d3. Он также использует старый метод d3.rebind, который удален из текущего d3 и который также имеет замену. Я попытался объединить эти два фрагмента, но это не удалось с ошибкой "Невозможно прочитать свойство" apply "из undefined.
Вот объединенный код:
<div id='map'></div>
<script>
function clickcancel() {
// Copies a variable number of methods from source to target.
d3.rebind = function(target, source) {
var i = 1, n = arguments.length, method;
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
return target;
};
// Method is assumed to be a standard D3 getter-setter:
// If passed with no arguments, gets the value.
// If passed with arguments, sets the value and returns the target.
function d3_rebind(target, source, method) {
return function() {
var value = method.apply(source, arguments);
return value === source ? target : value;
};
}
// we want to a distinguish single/double click
// details http://bl.ocks.org/couchand/6394506
var event = d3.dispatch('click', 'dblclick');
function cc(selection) {
var down, tolerance = 5, last, wait = null, args;
// euclidean distance
function dist(a, b) {
return Math.sqrt(Math.pow(a[0] - b[0], 2), Math.pow(a[1] - b[1], 2));
}
selection.on('mousedown', function() {
down = d3.mouse(document.body);
last = +new Date();
args = arguments;
});
selection.on('mouseup', function() {
if (dist(down, d3.mouse(document.body)) > tolerance) {
return;
} else {
if (wait) {
window.clearTimeout(wait);
wait = null;
event.dblclick.apply(this, args);
} else {
wait = window.setTimeout((function() {
return function() {
event.click.apply(this, args);
wait = null;
};
})(), 300);
}
}
});
};
return d3.rebind(cc, event, 'on');
}
var cc = clickcancel();
d3.select('#map').call(cc);
cc.on('click', function(d, index) {
d3.select('#map').text(d3.select('#map').text() + 'click, ');
});
cc.on('dblclick', function(d, index) {
d3.select('#map').text(d3.select('#map').text() + 'dblclick, ');
});
1 ответ
Более простой способ получить функциональность двойного щелчка:
//Set variables
<script type="text/javascript">
var clickDate = new Date();
var difference_ms;
//Set dragstarted functionality fired on '.call(d3.drag().on("start", dragstarted)'
function dragstarted(d) {
difference_ms = (new Date()).getTime() - clickDate.getTime();
clickDate = new Date();
if(difference_ms > 200) {
d3.select(this).classed("fixed", d.fixed = true);
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
} else {
d3.select(this).classed("fixed", d.fixed = false);
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
};
}
//Set dragended functionality fired on '.call(d3.drag().on("end", dragended)'
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
if(difference_ms < 200) {
d.fx = null;
d.fy = null;
};
}
Способ восстановления хитрого кода, на который я наткнулся, описан здесь в комментариях уважаемого nharrisanalyst. Хотя я до сих пор не понимаю, почему нужно идти по такому изощренному пути:
var cc = clickcancel();
d3.select('#map').call(cc); //#map is the element just for example
cc.on('click', function(d, index) {
d3.select('#map').text(d3.select('#map').text() + 'click, ');
});
cc.on('dblclick', function(d, index) {
d3.select('#map').text(d3.select('#map').text() + 'dblclick, ');
});
function clickcancel() {}