Javascript 剑道UI折线图中的点拖动

Javascript 剑道UI折线图中的点拖动,javascript,kendo-ui,Javascript,Kendo Ui,我有一个简单的剑道UI折线图,例如: <div id="chart"></div> <script> $("#chart").kendoChart({ series: [{ type: 'line', data: [200, 450, 300, 125] }] }); </sc

我有一个简单的剑道UI折线图,例如:

    <div id="chart"></div>      
    <script>
        $("#chart").kendoChart({
            series: [{
                type: 'line',
                data: [200, 450, 300, 125]
            }]
        });
    </script>

$(“#图表”)。肯多卡特({
系列:[{
键入:“行”,
数据:[200450300125]
}]
});

如何启用/实现点拖动?(即,我希望用户通过鼠标拖动垂直移动点)

我已经为剑道的工作示例更新了小提琴

我研究了图表的各个部分,使用SVG绘制图表

我已经更新了绘制图表的scratch模型,还添加了应该拖动的小代码

图表下方的圆圈。但它不是使用KendoDragable拖动的

样品

示例2这在用于Dragable的jQueryUI中运行良好,但由于SVG的存在,现在仍处于图形中


这应该给你一个好的开始。

你有几个问题需要克服——一个是我看到的剑道图上单击/拖动/悬停的默认行为。这应该很容易禁用,但这取决于您是否要将其中一些功能组合起来

第二个是刷新图表,剑道没有提供一种在没有完全重画的情况下更新图表的“好”方法。因此,作为拖动的一部分,我们必须移动SVG中的行。不幸的是,它们是路径的一部分,所以这更复杂

您完全可以将事件处理程序附加到各个循环,您可以使用另一个框架,如jqueryui()来实现这一点。但这就引出了第三个问题,您必须了解不同SVG元素的ID如何与您使用的实际数据相关。在内部,它为图形上的圆和路径创建了数字ID——您需要了解它们与数据点的关系

如果您已经完成了这项工作,并且可以访问jQuery UI,那么您可以尝试类似的方法(注意,SVG Dragable帮助改编自answer和MarmiK的小提琴)

包容需要只是绘图区域,而不是整个SVG,并且还需要更新路径。当你放下圆圈时,你可以作弊并使用剑道
.redraw()
方法,虽然这个圆圈不会像你想象的那么光滑,但它会起作用

然后,要动态更新路径,可以执行以下操作

var path = $('#k10014').attr('d'); // Get Path
path = path.substr(1);             // Remove M 
p_array = path.split(" ");         // Split into array
p_array[7] = ui.position.top;      // Change one value (but which one?)
path = "M"+ p_array.join(" ")      // Combine back with M
$('#k10014').attr('d', path);      // Update SVG

所以这非常接近——如果你能找出如何将每个圆与路径中的一个点关联起来(可能有一个模式与ID关联),那么你几乎肯定可以这样做

如果您想避免使用jQuery UI,可以手动实现所有拖动操作——这并不像上面已经完成的位置更新那么难

编辑

好的,我已经仔细考虑了一下——我可以看到图本身包含在两个内部元素中,所以我们可以使用jQuery来获得它。然后很容易找到第一条路径(即第一条线)并确定要拖动的圆,我制作了一个函数:

// This only works for one path ... but if you know the number of points
// then you can expand this easily ... 
function movePathForPointId(element, pos) {
   // Update pos to account for the circle radius 
   pos = pos + 2;

   // The graph is in two nested <g> elements, we can use this ... 

   // First find the position of the circle,     
   var pointIndex = $('svg g g circle').index(element); 

   // Get the first path in the graph 
   var pathElement = $('svg g g path').first();

   var path = pathElement.attr('d');     // Get Path String
   path = path.substr(1);                // Remove M 
   p_array = path.split(" ");            // Split into array
   p_array[(pointIndex * 2) + 1] = pos;  // Change one value (but which one?)
   path = "M"+ p_array.join(" ")         // Combine back with M
   pathElement.attr('d', path);          // Write new path back to SVG
   element.setAttribute('cy', pos);      // Update circle position
   return pointIndex;                    // Might be useful to update the data table
}
从那里我得到了一个工作,但这取决于你想对数据做什么。您可能需要解决如何解除剑道事件的绑定并绑定自己的剑道事件,或者使用上面的逻辑重新执行不同的拖动实现


但这应该会让你开始…

请发表一些自己的作品或小提琴,以便更好地理解,是的,这是可能的。我更新了我的问题。但问题是我不知道从哪里开始。我在详细研究这一部分,你需要从SVG命令开始,因为剑道it本身在图表的后端使用SVG查看生成图表的来源是的,我想我们可以从highcharts插件中得到启发,它显然也使用SVG:是的,它的即用功能,但是如果限制是剑道,我们有太多的工作要做。剑道支持拖放,但图表中不支持。因此,我们需要手动定义每个事件及其函数。非常感谢您的深入回答。你的小提琴看起来很棒。我会花一些时间来完全理解它,如果我成功地使用它,我肯定会验证这个答案。感谢您找到一种将SVG转换为HTML(SVG)的方法,这确实很有技巧:)@SpaceDog您知道如何将鼠标事件的Y坐标转换为图表值吗?@fiddler,我没有做那部分,因为我看不到一个简单的方法。您需要得到的是绘图区域的边界框——所有这些都包含在SVG中的第一个内部
g
元素中,看起来SVG中的第二条路径定义了网格线框。因此,您可以获取路径字符串
$(svg path).next().attr('d')
,然后对其进行处理以获得x/y值的最小值/最大值。这将为您提供角点——因此您应该能够推断相对于
(((maxY-minY)/(mouseY-plotAreaTopY))*(maxScaleY-minScaleY))+minScaleY的y位置
。我想;)
// This only works for one path ... but if you know the number of points
// then you can expand this easily ... 
function movePathForPointId(element, pos) {
   // Update pos to account for the circle radius 
   pos = pos + 2;

   // The graph is in two nested <g> elements, we can use this ... 

   // First find the position of the circle,     
   var pointIndex = $('svg g g circle').index(element); 

   // Get the first path in the graph 
   var pathElement = $('svg g g path').first();

   var path = pathElement.attr('d');     // Get Path String
   path = path.substr(1);                // Remove M 
   p_array = path.split(" ");            // Split into array
   p_array[(pointIndex * 2) + 1] = pos;  // Change one value (but which one?)
   path = "M"+ p_array.join(" ")         // Combine back with M
   pathElement.attr('d', path);          // Write new path back to SVG
   element.setAttribute('cy', pos);      // Update circle position
   return pointIndex;                    // Might be useful to update the data table
}
var chart = $("#chart").data("kendoChart");
var svg = chart.svg();
chart.destroy();
$("#chart").html(svg);