renderInventLine(); //渲染虚拟新路 renderAllStation(); //渲染所有的线路名称(右上角) renderBugLine(); //渲染问题路段 renderAllLine(); //渲染所有线路 renderAllPoint(); //渲染所有点 renderCurrentLine() //渲染当前选中的线路 renderCurrentPoint() //渲染当前选中的站点 zoomed() //缩放时执行的方法 getCenter() //获取虚拟线中心点的坐标 scale() //点击缩放按钮时执行的方法
下面是对应的方法体
svg.call(zoom); svg.call(zoom.transform, d3.zoomIdentity.translate((1 - baseScale) * transX, (1 - baseScale) * transY).scale(baseScale)); let pathArray = subway.getPathArray(); let pointArray = subway.getPointArray(); renderInventLine(); renderAllStation(); renderBugLine(); function renderInventLine() { let arr = subway.getInvent(); whole.selectAll('path') .data(arr) .enter() .append('path') .attr('d', d => d.path) .attr('class', d => d.lid) .attr('stroke', 'none') .attr('fill', 'none') } function renderAllLine() { for (let i = 0; i < pathArray.length; i++) { path.append('g') .selectAll('path') .data(pathArray[i].path) .enter() .append('path') .attr('d', d => d.path) .attr('lid', d => d.lid) .attr('id', d => d.id) .attr('class', 'lines origin') .attr('stroke', d => d.color) .attr('stroke-width', 7) .attr('stroke-linecap', 'round') .attr('fill', 'none') path.append('text') .attr('x', pathArray[i].lbx) .attr('y', pathArray[i].lby) .attr('dy', '1em') .attr('dx', '-0.3em') .attr('fill', pathArray[i].lc) .attr('lid', pathArray[i].lid) .attr('class', 'line-text origin') .attr('font-size', 14) .attr('font-weight', 'bold') .text(pathArray[i].lb) } } function renderAllPoint() { for (let i = 0; i < pointArray.length; i++) { for (let j = 0; j < pointArray[i].length; j++) { let item = pointArray[i][j]; let box = point.append('g'); if (item.ex) { box.append('image') .attr('href', './trans.png') .attr('class', 'points origin') .attr('id', item.sid) .attr('x', item.x - 8) .attr('y', item.y - 8) .attr('width', 16) .attr('height', 16) } else { box.append('circle') .attr('cx', item.x) .attr('cy', item.y) .attr('r', 5) .attr('class', 'points origin') .attr('id', item.sid) .attr('stroke', item.lc) .attr('stroke-width', 1.5) .attr('fill', '#ffffff') } box.append('text') .attr('x', item.x + item.rx) .attr('y', item.y + item.ry) .attr('dx', '0.3em') .attr('dy', '1.1em') .attr('font-size', 11) .attr('class', 'point-text origin') .attr('lid', item.lid) .attr('id', item.sid) .text(item.lb) } } } function renderCurrentLine(name) { let arr = subway.getCurrentPathArray(name); path.append('g') .attr('class', 'temp') .selectAll('path') .data(arr.path) .enter() .append('path') .attr('d', d => d.path) .attr('lid', d => d.lid) .attr('id', d => d.id) .attr('stroke', d => d.color) .attr('stroke-width', 7) .attr('stroke-linecap', 'round') .attr('fill', 'none') path.append('text') .attr('class', 'temp') .attr('x', arr.lbx) .attr('y', arr.lby) .attr('dy', '1em') .attr('dx', '-0.3em') .attr('fill', arr.lc) .attr('lid', arr.lid) .attr('font-size', 14) .attr('font-weight', 'bold') .text(arr.lb) } function renderCurrentPoint(name) { let arr = subway.getCurrentPointArray(name); for (let i = 0; i < arr.length; i++) { let item = arr[i]; let box = point.append('g').attr('class', 'temp'); if (item.ex) { box.append('image') .attr('href', './trans.png') .attr('x', item.x - 8) .attr('y', item.y - 8) .attr('width', 16) .attr('height', 16) .attr('id', item.sid) } else { box.append('circle') .attr('cx', item.x) .attr('cy', item.y) .attr('r', 5) .attr('id', item.sid) .attr('stroke', item.lc) .attr('stroke-width', 1.5) .attr('fill', '#ffffff') } box.append('text') .attr('class', 'temp') .attr('x', item.x + item.rx) .attr('y', item.y + item.ry) .attr('dx', '0.3em') .attr('dy', '1.1em') .attr('font-size', 11) .attr('lid', item.lid) .attr('id', item.sid) .text(item.lb) } } function renderBugLine(modal) { let bugLineArray = subway.getBugLineArray(modal); d3.selectAll('.origin').remove(); renderAllLine(); renderAllPoint(); bugLineArray.forEach(d => { console.log(d) d.lines.forEach(dd => { d3.selectAll(`path#${dd}`).attr('stroke', '#eee'); }) d.points.forEach(dd => { d3.selectAll(`circle#${dd}`).attr('stroke', '#ddd') d3.selectAll(`text#${dd}`).attr('fill', '#aaa') }) }) d3.selectAll('.points').on('click', function () { let id = d3.select(this).attr('id'); let bool = judgeBugPoint(bugLineArray, id); if (bool) { let x, y; if (d3.select(this).attr('href')) { x = parseFloat(d3.select(this).attr('x')) + 8; y = parseFloat(d3.select(this).attr('y')) + 8; } else { x = d3.select(this).attr('cx'); y = d3.select(this).attr('cy'); } let toolX = (x * currentScale + transX - ((1 - currentScale) * transX - currentX)) * deviceScale; let toolY = (y * currentScale + transY - ((1 - currentScale) * transY - currentY)) * deviceScale; let toolH = document.getElementById('tooltip').offsetHeight; let toolW = 110; if (toolY < 935 / 2) { tooltip.style('left', `${toolX - toolW}px`).style('top', `${toolY + 5}px`); } else { tooltip.style('left', `${toolX - toolW}px`).style('top', `${toolY - toolH - 5}px`); } } }); } function judgeBugPoint(arr, id) { if (!arr || !arr.length || !id) return false; let bugLine = arr.filter(d => { return d.points.indexOf(id) > -1 }); if (bugLine.length) { removeTooltip() tooltip.select('#tool-head').html(`<span>${id}</span><div>×</div>`); bugLine.forEach(d => { let item = tooltip.select('#tool-body').append('div').attr('class', 'tool-item'); item.html(` <div> <div> <span>${d.lb}</span> </div> <div> <div>封路时间</div><div>${d.duration}</div> </div> <div> <div>封路原因</div><div>${d.cause}</div> </div> <div> <div>封路路段</div><div>${d.start}-${d.end}</div> </div> </div> `) }) d3.select('#tooltip').style('display', 'block'); return true; } else { return false; } } function removeTooltip() { d3.selectAll('.tool-item').remove(); d3.select('#tooltip').style('display', 'none'); } function zoomed() { removeTooltip(); let {x, y, k} = d3.event.transform; currentScale = k; currentX = x; currentY = y; group.transition().duration(50).ease(d3.easeLinear).attr("transform", () => `translate(${x + transX * k}, ${y + transY * k}) scale(${k})`) } function getCenter(str) { if (!str) return null; let x, y; let tempArr = []; let tempX = []; let tempY = []; str.split(' ').forEach(d => { if (!isNaN(d)) { tempArr.push(d) } }) tempArr.forEach((d, i) => { if (i % 2 == 0) { tempX.push(parseFloat(d)) } else { tempY.push(parseFloat(d)) } }) x = (d3.min(tempX) + d3.max(tempX)) / 2; y = (d3.min(tempY) + d3.max(tempY)) / 2; return [x, y] } function renderAllStation() { let nameArray = subway.getLineNameArray(); let len = Math.ceil(nameArray.length / 5); let box = d3.select('#menu').append('div') .attr('class', 'name-box') for (let i = 0; i < len; i++) { let subwayCol = box.append('div') .attr('class', 'subway-col') let item = subwayCol.selectAll('div') .data(nameArray.slice(i * 5, (i + 1) * 5)) .enter() .append('div') .attr('id', d => d.lid) .attr('class', 'name-item') item.each(function (d) { d3.select(this).append('span').attr('class', 'p_mark').style('background', d.lc); d3.select(this).append('span').attr('class', 'p_name').text(d.lb); d3.select(this).on('click', d => { selected = true; d3.selectAll('.origin').style('opacity', 0.1); d3.selectAll('.temp').remove(); renderCurrentLine(d.lid); renderCurrentPoint(d.lid); let arr = getCenter(d3.select(`path.${d.lid}`).attr('d')); svg.call(zoom.transform, d3.zoomIdentity.translate((width / 2 - transX) - arr[0] - (arr[0] + transX) * (currentScale - 1), (height / 2 - transY) - arr[1] - (arr[1] + transY) * (currentScale - 1)).scale(currentScale)); }) }) } } function scale(type) { if (type && currentScale + scaleStep <= scaleExtent[1]) { svg.call(zoom.transform, d3.zoomIdentity.translate((1 - currentScale - scaleStep) * transX - ((1 - currentScale) * transX - currentX) * (currentScale + scaleStep) / currentScale, (1 - currentScale - scaleStep) * transY - ((1 - currentScale) * transY - currentY) * (currentScale + scaleStep) / currentScale).scale(currentScale + scaleStep)); } else if (!type && currentScale - scaleStep >= scaleExtent[0]) { svg.call(zoom.transform, d3.zoomIdentity.translate((1 - (currentScale - scaleStep)) * transX - ((1 - currentScale) * transX - currentX) * (currentScale - scaleStep) / currentScale, (1 - (currentScale - scaleStep)) * transY - ((1 - currentScale) * transY - currentY) * (currentScale - scaleStep) / currentScale).scale(currentScale - scaleStep)); } }
上面是大部分代码,想看全部的可以查看demo。
总结