赞
踩
效果如图,这次直接上实战。
在数据可视化中,交互是非常重要的一部分,能够使用户与图表进行互动并进行自定义操作。其中之一就是拖拽功能,可以让用户自由地移动元素,改变元素的位置或顺序。在D3.js中,我们可以使用d3-drag来实现这样的交互式拖拽功能。
首先,我们需要在HTML文件中引入d3.js和d3-drag库。可以通过CDN或本地文件的方式引入,如下所示:
接下来,我们需要创建一个可拖拽的元素。在这个示例中,我们将创建一个简单的矩形,并添加拖拽功能。首先,在HTML中创建一个SVG容器:
html复制代码<svg id="container" width="400" height="300"></svg>
然后,在JavaScript代码中使用D3.js创建一个矩形元素,并添加拖拽功能:
- javascript复制代码// 创建一个SVG容器
- const svg = d3.select("#container");
-
- // 创建矩形元素
- const rect = svg.append("rect")
- .attr("x", 100)
- .attr("y", 100)
- .attr("width", 50)
- .attr("height", 50)
- .attr("fill", "blue");
-
- // 创建拖拽行为
- const drag = d3.drag()
- .on("start", dragStarted)
- .on("drag", dragged)
- .on("end", dragEnded);
-
- // 将拖拽行为应用到矩形元素上
- rect.call(drag);
-
- // 拖拽开始时的回调函数
- function dragStarted(event, d) {
- d3.select(this).raise().attr("fill", "red");
- }
-
- // 拖拽过程中的回调函数
- function dragged(event, d) {
- d3.select(this)
- .attr("x", event.x)
- .attr("y", event.y);
- }
-
- // 拖拽结束时的回调函数
- function dragEnded(event, d) {
- d3.select(this).attr("fill", "blue");
- }
在上面的代码中,我们首先使用d3.select()选择了SVG容器,并使用append()方法创建了一个矩形元素。然后,我们创建了一个拖拽行为,并将其应用到矩形元素上,通过调用rect.call(drag)。
在拖拽行为的回调函数中,我们可以定义拖拽开始、拖拽过程和拖拽结束时的操作。在拖拽开始时,我们将选中的元素提到最前面,并改变其填充颜色。在拖拽过程中,我们使用event.x和event.y来更新元素的位置。在拖拽结束时,我们将填充颜色恢复为初始值。
我们已经掌握了drag的基本用法,下面我们来开发一个颜色匹配的小游戏吧! 游戏思路
这是一个有意思的小游戏,适合小朋友玩哦。改造一个可以开发出各种类似的游戏,比如动物认识。人物认识,形状认识。呵呵
代码如下,自己看,懒得解释了。
- javascript复制代码// drag
- let dom = document.createElement('div');
- document.body.appendChild(dom);
-
- let padding = 30;
- let svgWidth = 600;
- let svgHeight = 300;
-
- let svg = d3.select(dom)
- .append("svg")
- .attr("width", svgWidth)
- .attr("height", svgHeight)
- .style('border', '1px solid #999999')
-
- // 定义5个颜色
- let colors = [
- {
- id: 0,
- name: '橙色',
- color: '#ff6633'
- },
- {
- id: 1,
- name: '蓝色',
- color: '#3399ff'
- },
- {
- id: 2,
- name: '绿色',
- color: '#33cc33'
- },
- {
- id: 3,
- name: '紫色',
- color: '#cc33ff'
- },
- {
- id: 4,
- name: '黄色',
- color: '#ffcc00'
- }
- ]
-
- // 绘制5个矩形
- let rectWidth = 100;
- let rectHeight = 100;
- let rectPadding = 10;
-
- let pos = {}
-
- // 绘制5个矩形背景边框
- let gback = svg.append('g').attr('class', 'back');
- let rectBacks = gback.selectAll('rect')
- .data(colors)
- .enter()
- .append('rect')
- .attr('x', (d, i) => {
- let x = padding + (rectWidth + rectPadding) * i;
- pos[d.id] = [x, padding]
- return x;
- })
- .attr('cid', d => d.name)
- .attr('ok', 'fail')
- .attr('y', padding)
- .attr('width', rectWidth)
- .attr('height', rectHeight)
- .attr('fill', 'none')
- .attr('stroke', '#000000')
- .attr('stroke-width', '2px')
-
- let _colors = JSON.parse(JSON.stringify(colors));
- // 打乱顺序
- _colors.sort(function () {
- return Math.random() - 0.5;
- })
-
- let grect = svg.append('g').attr('class', 'rect');
- let rects = grect.selectAll('rect')
- .data(_colors)
- .enter()
- .append('rect')
- .attr('cid', d => d.name)
- .attr('x', (d, i) => {
- return padding + (rectWidth + rectPadding) * i + rectWidth * 0.1;
- })
- .attr('y', (d, i) => {
- return padding + rectHeight + 50;
- })
- .attr('width', rectWidth * 0.8)
- .attr('height', rectHeight * 0.8)
- .attr('fill', d => d.color)
-
- // 在背景矩形上添加文字 颜色名称
- let gtext = svg.append('g').attr('class', 'text');
- let texts = gtext.selectAll('text')
- .data(colors)
- .enter()
- .append('text')
- .attr('x', (d, i) => {
- return padding + (rectWidth + rectPadding) * i + rectWidth / 2;
- })
- .attr('y', (d, i) => {
- return padding + rectHeight / 2;
- })
- .attr('text-anchor', 'middle')
- .attr('dominant-baseline', 'middle')
- .attr('fill', '#000000')
- .attr('font-size', '20px')
- .text(d => d.name)
- .style('pointer-events', 'none');
-
- // 提示文本 干得漂亮,你完成了所有的颜色匹配
- let infoText = svg
- .append('text')
- .attr('x', svgWidth / 2)
- .attr('y', svgHeight - 80)
- .attr('text-anchor', 'middle')
- .attr('dominant-baseline', 'middle')
- .attr('fill', '#000000')
- .attr('font-size', '24px')
- .text('干得漂亮Tom,你完成了所有的颜色匹配!')
- .style('pointer-events', 'none')
- .style('opacity', 0);
- let drag = d3.drag()
- .on('start', function (d, i) {
- d3.select(this)
- .raise()// 提升层级 使得当前元素在最上层
- .transition()
- .attr('stroke', '#000000')
- .attr('stroke-width', '2px')
- // 鼠标样式
- .style('cursor', 'move')
-
- })
- .on('drag', function (d) {
- let dx = d3.event.dx;
- let dy = d3.event.dy;
- let x = d3.select(this).attr('x');
- let y = d3.select(this).attr('y');
- d3.select(this)
- .attr('x', +x + dx)
- .attr('y', +y + dy);
- // 矩形中心点坐标
- let cx = +x + dx + (rectWidth * 0.8) / 2;
- let cy = +y + dy + (rectHeight * 0.8) / 2;
- let cid = d3.select(this).attr('cid');
- dis(d3.select(this), cx, cy, cid);
-
-
-
- })
- .on('end', function (d, i) {
- d3.select(this)
- .transition()
- .attr('stroke', 'none')
- //鼠标样式
- .style('cursor', 'default')
-
- if (d3.select(this).attr('ok') === 'success') {
- // 吸附到背景矩形上
- let _x = pos[d.id][0] + rectWidth / 2 - rectWidth * 0.8 / 2;
- let _y = pos[d.id][1] + rectHeight / 2 - rectHeight * 0.8 / 2;
- d3.select(this)
- .transition()
- .attr('x', _x)
- .attr('y', _y)
- }
- goodJob();
- })
-
- rects.call(drag);
-
- function dis(rect, x, y, cid) {
- // 计算x y和 rectBacks 中心点的距离 如果小于 30 就 变色
- rectBacks.each(function (d, i) {
- let cx = pos[i][0] + rectWidth / 2;
- let cy = pos[i][1] + rectHeight / 2;
- let _cid = d3.select(this).attr('cid');
- let distance = Math.sqrt(Math.pow(cx - x, 2) + Math.pow(cy - y, 2));
- if (distance < 30 && cid == _cid) {
- d3.select(this)
- .attr('stroke', d.color)
- .attr('ok', 'success')
- rect.attr('ok', 'success')
- } else {
- if (cid != _cid) return;
- d3.select(this)
- .attr('stroke', '#000000')
- .attr('ok', 'fail')
- rect.attr('ok', 'fail')
- }
- if (d3.select(this).attr('ok') != 'success') {
- gogogo = false;
- }
- })
-
- }
-
- function goodJob() {
- let gogogo = true;
- rectBacks.each(function (d, i) {
- if (d3.select(this).attr('ok') === 'fail') {
- gogogo = false;
- }
- })
- if (gogogo) {
- infoText
- .transition()
- .style('opacity', 1)
- } else {
- infoText
- .transition()
- .style('opacity', 0)
- }
- }
在线地址:scqilin.github.io/d3js/intera…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。