使用一些JavasSript和CSS,您可以在不使用canvas或SVG的情况下实现这一目标。这是一个示例:
<Grid>
<WrapperView TitleText ="Step X Title Text">
<!-- XAML for Step X View -->
</WrapperView>
</Grid>
function getPosition(el) {
return {
x: el.offsetLeft + el.offsetWidth / 2,y: el.offsetTop + el.offsetHeight / 2
};
}
function getDistance(a,b) {
const from = getPosition(a);
const to = getPosition(b);
return {
//https://stackoverflow.com/a/17628488/529024
distance: Math.hypot(from.x - to.x,from.y - to.y),angle: Math.atan2(to.x - from.x,from.y - to.y) * 180 / Math.PI,position: {
start: from,end: to
}
}
}
function init(){
// Get values and elements then set style
const values = getDistance(
document.getElementById("start"),document.getElementById("end")
);
let wrapper = document.getElementById('wrapper');
let arrow = document.getElementById('arrow');
let bottom = wrapper.offsetHeight - values.position.start.y;
arrow.style.height = values.distance + "px";
arrow.style.transform = `rotate(${values.angle}deg)`;
arrow.style.bottom = bottom + "px";
arrow.style.left = values.position.start.x + "px";
}
init();
window.addEventListener('resize',function(){
init();
});
#wrapper {
position: relative;
left: 50px;
top: 100px;
}
#arrow {
position: absolute;
width: 2px;
background-color: red;
transform-origin: bottom center;
}
#arrow::before {
position: absolute;
height: 0px;
width: 0px;
border: 6px solid transparent;
border-bottom: 8px solid red;
content: "";
bottom: 100%;
left: 50%;
transform: translateX(-50%);
}
,
您可以使用我的解决方案尚未完成绘制箭头,
让我们创建一个画布,并根据起点和终点的计算从两点画一条线。
Example running: https://jsfiddle.net/tabvn/uk7hsj3a
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<table id="my-table">
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td id="end">9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td id="start">0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
<script type="text/javascript">
var table = document.getElementById('my-table')
var startElement = document.getElementById('start')
var endElement = document.getElementById('end')
var startPoint = {x: startElement.offsetLeft + table.offsetLeft,y: startElement.offsetTop + table.offsetTop}
var endPoint = {x: endElement.offsetLeft + table.offsetLeft,y: endElement.offsetTop + table.offsetTop}
var canvas = document.createElement('canvas')
canvas.width = table.clientWidth
canvas.height = table.clientHeight
canvas.style.position = 'absolute'
canvas.style.top = startPoint.y < endPoint.y ? startPoint.y + 'px' : endPoint.y + 'px'
canvas.style.left = startPoint.x < endPoint.x ? startPoint.x + 'px' : endPoint.x + 'px'
var ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.strokeStyle = 'red'
ctx.fillStyle = 'red'
ctx.moveTo(startPoint.x - (startElement.clientWidth / 2),startPoint.y)
ctx.lineTo(endPoint.x - (endElement.clientWidth / 2),endPoint.y)
ctx.stroke()
document.body.insertBefore(canvas,table,30)
</script>
</body>
</html>
,
JavaScript解决方案:
drawLine();
function drawLine () {
var table = document.getElementById('my-table')
var startElement = document.getElementById('start')
var endElement = document.getElementById('end')
let arrowRadius = 10;
let xStart = null;
let xEnd = null;
if (startElement.offsetLeft > endElement.offsetLeft) {
xStart = startElement.offsetLeft + (arrowRadius/2);//to add padding just add more wherever theres this pattern
xEnd = endElement.offsetLeft + endElement.offsetWidth / 2;
} else if (startElement.offsetLeft < endElement.offsetLeft) {
xStart = startElement.offsetLeft + startElement.offsetWidth - (arrowRadius/2);
xEnd = endElement.offsetLeft;
} else {
xStart = startElement.offsetLeft + startElement.offsetWidth / 2;
xEnd = endElement.offsetLeft + endElement.offsetWidth / 2;
}
let yStart = null;
let yEnd = null;
if (startElement.offsetTop > endElement.offsetTop) {
yStart = startElement.offsetTop + (arrowRadius/2);
yEnd = endElement.offsetTop + endElement.offsetHeight + (arrowRadius/2);
} else if (startElement.offsetTop < endElement.offsetTop) {
yStart = startElement.offsetTop + startElement.offsetHeight - (arrowRadius/2);
yEnd = endElement.offsetTop - (arrowRadius/2);
} else {
yStart = startElement.offsetTop + startElement.offsetHeight / 2;
yEnd = endElement.offsetTop + endElement.offsetHeight / 2;
}
let coordBegin = {
x: xStart,y: yStart
};
let coordEnd = {
x: xEnd,y: yEnd
};
var canvas = document.createElement('canvas')
canvas.width = table.offsetWidth
canvas.height = table.offsetHeight
canvas.style.position = 'absolute'
var ctx = canvas.getContext('2d')
drawArrowhead(ctx,coordBegin,coordEnd,arrowRadius);
ctx.beginPath()
ctx.strokeStyle = 'red'
ctx.fillStyle = 'red'
ctx.moveTo(coordBegin.x,coordBegin.y)
ctx.lineTo(coordEnd.x,coordEnd.y)
ctx.stroke()
document.body.insertBefore(canvas,table)
}
function drawArrowhead(context,from,to,radius) {
var x_center = to.x;
var y_center = to.y;
var angle;
var x;
var y;
context.beginPath();
angle = Math.atan2(to.y - from.y,to.x - from.x)
x = radius * Math.cos(angle) + x_center;
y = radius * Math.sin(angle) + y_center;
context.moveTo(x,y);
angle += (1.0/3.0) * (2 * Math.PI)
x = radius * Math.cos(angle) + x_center;
y = radius * Math.sin(angle) + y_center;
context.lineTo(x,y);
angle += (1.0/3.0) * (2 * Math.PI)
x = radius *Math.cos(angle) + x_center;
y = radius *Math.sin(angle) + y_center;
context.lineTo(x,y);
context.closePath();
context.fillStyle = 'red';
context.fill();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<table id="my-table">
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td id="end">9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td id="start">0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
</body>
</html>
,
您可以使用SVG元素和CSS样式来覆盖表格的绝对位置。并通过getBoundingClientRect()
这样的JavaScript DOM API获取起点和终点
Here是一个演示。 (使用Angular制造,但是您可以在任何地方使用它。纯JavaScript示例如下所示。)
const startElement = document.querySelector('#start');
const endElement = document.querySelector('#end');
const startRect = startElement.getBoundingClientRect();
const endRect = endElement.getBoundingClientRect();
const startX = startRect.right;
const startY = startRect.top;
const endX = endRect.left;
const endY = endRect.bottom;
您可以动态更改开始和结束。您只需重新调用该方法即可获得职位。请注意,我使用左,上,右按钮将箭头放置在元素的边缘。您可以通过比较两个位置来计算中心点或边缘。
您必须将svg放在桌子上。您可以通过设置css position: absolute; left: 0; top: 0
来实现。但请注意,您的父母也应具有position
属性。例如position: relative
。
更新:Here是一个纯JavaScript演示。单击左侧以查看所有文件,然后选择index.js以查看JS内容。 (如VS Code中的代码)。
完整代码:
<table style="position: absolute; left: 0; top: 0;">
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td id="end">9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td id="start">0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<svg style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 1">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="5" refY="3" orient="auto"
markerUnits="strokeWidth" viewBox="0 0 20 20">
<path d="M0,0 L0,6 L9,3 z" fill="#f00" />
</marker>
</defs>
<line id="svg-line" stroke="#f00" stroke-width="5"
marker-end="url(#arrow)" />
</svg>
</table>
<script>
const svgLine = document.querySelector('#svg-line');
const startElement = document.querySelector("#start");
const endElement = document.querySelector("#end");
const startRect = startElement.getBoundingClientRect();
const endRect = endElement.getBoundingClientRect();
const startX = startRect.right;
const startY = startRect.top;
const endX = endRect.left;
const endY = endRect.bottom;
svgLine.setAttribute('x1',startX);
svgLine.setAttribute('y1',startY);
svgLine.setAttribute('x2',endX);
svgLine.setAttribute('y2',endY);
</script>
只需将上面的代码复制到一个新的空html文件中,然后在浏览器中运行它即可。
顺便说一句。您也可以使用画布执行此操作。 (替代svg)
,
这是我的处理方式:
svg元素使用表的大小作为viewBox值。
您正在计算需要关联的像元的大小和位置,并使用此位置画线。箭头的顶端使用了标记。
请调整窗口大小:
let cells = Array.from(document.querySelectorAll("td"));
// index of cells to be correlated
let n1 = 90;
let n2 = 9;
// a function to draw the arrow
function drawArrow(){
//get the size of the table
let size = theTable.getBoundingClientRect();
//set the viewBox attribute for the svg element
theSVG.setAttributeNS(null,"viewBox",`0 0 ${size.width} ${size.height}`)
//get the size and the position of the cells
let c1 = cells[n1].getBoundingClientRect();
let c2 = cells[n2].getBoundingClientRect();
//set the x1,y1,x2,y2 attributes of the line
theLine.setAttributeNS(null,"x1",`${c1.left + c1.width/2}`);
theLine.setAttributeNS(null,"y1",`${c1.top + c1.height/2}`);
theLine.setAttributeNS(null,"x2",`${c2.left + c2.width/2}`);
theLine.setAttributeNS(null,"y2",`${c2.top + c1.height/2}`);
}
drawArrow()
window.setTimeout(function() {
drawArrow()
window.addEventListener('resize',drawArrow,false);
},15);
body {
margin: 0;
padding: 0;
}
table,svg{
width: 100%;
border-collapse: collapse;
margin: 0;
position:absolute;
}
td {
border: 1px solid #d9d9d9;
padding: 0.5em;
text-align: center;
}
svg{background:rgba(0,255,.5)}
<table id="theTable">
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td id="end">9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
<tr><td id="start">0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><tr>
</table>
<svg id="theSVG">
<defs>
<marker id="arrow" markerWidth="6" markerHeight="12" refX="8" refY="6" orient="auto">
<path d="M 0 0 L 8 6 L 0 12" />
</marker>
</defs>
<line id="theLine" marker-end="url(#arrow)" stroke="black" />
</svg>
更新:
由于有人评论说调整箭头大小会丢失它的位置,所以我要添加gif:
,
您需要将表格放入div中并指定位置为relative的属性
然后为箭头编写HTML(如果需要,请使用图片),并为其赋予绝对属性,然后根据需要使用其样式(顶部,左侧,右侧)。
在https://www.w3schools.com/css/css_positioning.asp
上了解有关位置属性的更多信息
本文链接:https://www.f2er.com/3123702.html