• 在d3中使用2D.js获取图形间的交点


    在d3中并不没有什么方法能直接获取到两条linepath或两个其他图形的交点,所以我们借助2D.js帮助我们计算交点。

    2D.js

    • 以两条线的为例

    • 获取svg中两条line并初始化

    • 通过Intersection.intersectShapes来计算交点

    绘制交点

    • 以直线和曲线为例,先绘制图形。
    
    <!DOCTYPE html>
    <html>
    
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    
    	<body>
    		<div id="test-svg">
    		</div>
    	</body>
    	<script src="https://d3js.org/d3.v5.js"></script>
    	<script type="text/javascript" src="js/2D.js"></script>
    	<script>
    		window.onload = function() {
    
    			// 数据
    			var data = [{
    				date: new Date(2019, 3, 24),
    				value: 23.24
    			}, {
    				date: new Date(2019, 3, 25),
    				value: 72.15
    			}, {
    				date: new Date(2019, 3, 26),
    				value: 38.84
    			}, {
    				date: new Date(2019, 3, 27),
    				value: 58.62
    			}, {
    				date: new Date(2019, 3, 30),
    				value: 10.80
    			}, {
    				date: new Date(2019, 4, 1),
    				value: 85.47
    			}];
    
    			var data2 = [{
    				date: new Date(2019, 3, 24),
    				value: 18.24
    			}, {
    				date: new Date(2019, 4, 1),
    				value: 90.47
    			}];
    
    			var width = 800,
    				height = 400,
    				padding = {
    					top: 40,
    					right: 40,
    					bottom: 40,
    					left: 40
    				};
    
    			var colors = d3.schemeSet2;
    			var svg = d3.select("#test-svg")
    				.append('svg')
    				.attr('width', width + 'px')
    				.attr('height', height + 'px');
    
    			// x轴:时间轴
    			var xScale = d3.scaleTime()
    				.domain(d3.extent(data, function(d) {
    					return d.date;
    				}))
    				.range([padding.left, width - padding.right]);
    
    			var xAxis = d3.axisBottom()
    				.scale(xScale)
    				.tickSize(10);
    
    			svg.append('g')
    				.call(xAxis)
    				.attr("transform", "translate(0," + (height - padding.bottom) + ")")
    				.selectAll("text")
    				.attr("font-size", "10px")
    				.attr("dx", "50px");
    
    			var ymax = d3.max(data, function(d) {
    				return d.value;
    			});
    
    			// y轴
    			var yScale = d3.scaleLinear()
    				.domain([0, ymax])
    				.range([height - padding.bottom, padding.top]);
    
    			var yAxis = d3.axisLeft()
    				.scale(yScale)
    				.ticks(10);
    
    			svg.append('g')
    				.call(yAxis)
    				.attr("transform", "translate(" + padding.left + ",0)");
    
    			// 曲线	
    			var curveLine = d3.line()
    				.x(function(d) {
    					return xScale(d.date);
    				})
    				.y(function(d) {
    					return yScale(d.value);
    				})
    				.curve(d3.curveCatmullRom.alpha(0.5));
    
    			// 直线
    			var line = d3.line()
    				.x(function(d) {
    					return xScale(d.date);
    				})
    				.y(function(d) {
    					return yScale(d.value);
    				});
    
    			var container = svg.append("g");
    
    			container.append("path")
    				.datum(data)
    				.attr("d", curveLine)
    				.attr("class", "cmn")
    				.attr('stroke', '#FFA354')
    				.attr("fill", "none");
    
    			container.append("path")
    				.datum(data2)
    				.attr("d", line)
    				.attr("class", "csmn")
    				.attr('stroke', '#FFA354')
    				.attr("fill", "none");
    
    			
    		}
    	</script>
    
    </html>
    
    
    

    • 使用2D.js获取绘制交点

    • Intersection.intersectShapes(shapes[0], shapes[1])

    var shapes = [];
    
    			var children = container.selectAll("path");
                
                // 获取path
    			for(var i = 0; i < children._groups[0].length; i++) {
    				var child = children._groups[0][i];
    				var shape = new Path(child);
    				shapes.push(shape);
    			}
                
                // 计算交点
    			var inter = Intersection.intersectShapes(shapes[0], shapes[1]);
                
                // 绘制交点
    			svg.selectAll("circle")
    				.data(inter.points)
    				.join("circle")
    				.attr("r", 3)
    				.attr("cx", function(d) {
    					return d.x;
    				})
    				.attr("cy", function(d) {
    					return d.y;
    				})
    				.attr("fill", "steelblue");
    
    

    同理也可以使用两个图形

    • 两个rect
    
    svg.append("rect")
    				.attr("x", 100)
    				.attr("y", 100)
    				.attr("width", 100)
    				.attr("height", 200)
    				.attr("fill", "none")
    				.attr('stroke', '#FFA354')
    				.attr('stroke-width', 1.5);
    
    			svg.append("rect")
    				.attr("x", 0)
    				.attr("y", 150)
    				.attr("width", 300)
    				.attr("height", 100)
    				.attr("fill", "none")
    				.attr('stroke', '#FFA354')
    				.attr('stroke-width', 1.5);
    
    			var shapes = [];
    
    			var children = svg.selectAll("rect");
                
                // 获取path
    			for(var i = 0; i < children._groups[0].length; i++) {
    				var child = children._groups[0][i];
    				var shape = new Rectangle(child);
    				shapes.push(shape);
    			}
                
                // 计算交点
    			var inter = Intersection.intersectShapes(shapes[0], shapes[1]);
    			
                // 绘制交点
    			svg.selectAll("circle")
    				.data(inter.points)
    				.join("circle")
    				.attr("r", 3)
    				.attr("cx", function(d) {
    					return d.x;
    				})
    				.attr("cy", function(d) {
    					return d.y;
    				})
    				.attr("fill", "steelblue");
    
    

    • 注:旋转和缩放后可能会存在问题,计算出的交点还是没有操作之前的。
    
    .attr('transform','rotate(30)')
    
    

    
    .attr('transform','scale(1.2,1.2)')
    
    

  • 相关阅读:
    BestCoder Round #71 (div.2) (hdu 5621)
    BestCoder Round #71 (div.2) (hdu 5620 菲波那切数列变形)
    BestCoder Round #69 (div.2) Baby Ming and Weight lifting(hdu 5610)
    BestCoder Round #70 Jam's math problem(hdu 5615)
    BestCoder Round #68 (div.2) tree(hdu 5606)
    poj 2299 Ultra-QuickSort(归并排序或是bit 树+离散化皆可)
    hdu 3874 Necklace(bit树+事先对查询区间右端点排序)
    HDU 4300 Clairewd’s message(KMP)
    HDU 3308 LCIS(线段树单点更新区间合并)
    PKU 3667 Hotel(线段树)
  • 原文地址:https://www.cnblogs.com/chenjy1225/p/11013681.html
Copyright © 2020-2023  润新知