将箭头“映射”到字符

Posted

技术标签:

【中文标题】将箭头“映射”到字符【英文标题】:"Mapping" arrows to characters 【发布时间】:2013-07-23 01:27:18 【问题描述】:

我真的不知道如何命名,如果标题令人困惑,请见谅。

我想要一种方法来绘制各种类型/方向的箭头,具体取决于它们指向的字符串的长度(以及其他因素)。见下图。

我不能只制作一张图片(比如这张),因为数字和字母是随机生成的。所以,我不知道一个数字是 1、2 还是 3 位数字(或者它是否会附有字母)。

基本上,有没有办法将“节点”的中心(可能是错误的词,但我不知道还能说什么)与箭头的起点和终点连接起来?

我愿意接受所有的网络编程。 javascript 库、Raphael.js、canvas.... 最佳创意胜出!

【问题讨论】:

如果是随机生成的,连接的逻辑是什么? @redreggae:这是我想要弄清楚的一部分。每个“事物/节点”都需要被识别(可能通过 )。然后我需要指定应该连接哪两个(或更多)。 您必须确定字符串在屏幕上的位置并编写某种箭头生成器。这并不容易。没有人会给你一个解决方案 - 展示一些工作。 @Diodeus:我不知道从哪里开始。这就是为什么没有工作。我需要点子。 这些数字是“随机生成的”之后,您是否确切地知道哪些数字/符号构成了您的每个数学短语?另外,您是否控制页面上不同短语的绘制位置?如果您对这两个问题都回答“是”,那么您的解决方案就会变得容易得多。如果你对第一个问题回答“否”,除了尝试非常复杂的字符识别之外,你没有答案。你如何确定你希望箭头从哪里开始和结束——你是在短语中指定一个字母,还是什么? 【参考方案1】:

这种设计将箭头映射到数学短语中的任何指定字符

此设计使用 html 画布绘制文本数学短语和连接箭头。

它的工作原理是让您在数学短语中指定任何字符并调用在该字符上绘制向上或向下箭头。

    // draw an up arrow on the current phrase as character#1
    drawUpArrow(phrase,30,80,1,"red");

    // draw a down arrow on the current phrase at character#5
    drawDownArrow(phrase,30,80,5,"green");

您可以根据需要指定任意数量的箭头。

    // draw arrow on characters #1,3,5,7
    drawUpArrow(phrase,30,80,1,"red");
    drawDownArrow(phrase,30,80,3,"green");
    drawDownArrow(phrase,30,80,5,"green");
    drawDownArrow(phrase,30,80,7,"green");

这是代码和小提琴:http://jsfiddle.net/m1erickson/dUexE/

 <!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body background-color: ivory; padding:15px; 
    canvasborder:1px solid red;
</style>

<script>
$(function()

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    ctx.font="14pt Verdana";

    var phrase="(5c + 3)(7n + 2)";
    var connectorPoints=[]
    var connectorPoints2=[]

    // draw start-arrow at character #1
    // draw end-arrows at characters #5 and #12
    drawPhrase(phrase,30,80);
    connectorPoints.push(drawUpArrow(phrase,30,80,2,"red"));
    connectorPoints.push(drawDownArrow(phrase,30,80,10,"green"));
    connectorPoints.push(drawDownArrow(phrase,30,80,15,"green"));
    temporaryConnector(connectorPoints,"green");

    connectorPoints2.push(drawDownArrowUnder(phrase,30,80,7,"red"));
    connectorPoints2.push(drawUpArrowUnder(phrase,30,80,10,"green"));
    connectorPoints2.push(drawUpArrowUnder(phrase,30,80,15,"green"));
    temporaryConnector(connectorPoints2,"green");



    // draw the phrase at X/Y
    function drawPhrase(text,x,y)
        ctx.fillStyle="black";
        ctx.fillText(text,x,y);
    

    function calcMidX(text,x,letterNumber)
        var text1=text.substr(0,letterNumber-1);
        var text2=text.substr(0,letterNumber);

        var startX=ctx.measureText(text1).width;
        var endX=ctx.measureText(text2).width;
        var midX=startX+(endX-startX)/2;

        return(midX);        
    


    function drawArrow(x,y,y1,y2,y3,color)
        // arrowhead
        ctx.beginPath();
        ctx.moveTo(x,y-y1);
        ctx.lineTo(x-5,y-y2);
        ctx.lineTo(x+5,y-y2);
        ctx.closePath();
        ctx.fillStyle=color;
        ctx.fill();
        // arrowtail
        ctx.beginPath();
        ctx.moveTo(x,y-y2);
        ctx.lineTo(x,y-y3);
        ctx.strokeStyle=color;
        ctx.lineWidth=3;
        ctx.stroke();
    

    // draw a down-arrow at the specified letterNumber
    function drawDownArrow(text,x,y,letterNumber,color)
        x+=calcMidX(text,x,letterNumber);
        drawArrow(x,y,18,28,35,color);
        return(x:x,y:y-35);
    

    // draw an up-arrow at the specified letterNumber
    function drawUpArrow(text,x,y,letterNumber,color)
        x+=calcMidX(text,x,letterNumber);
        drawArrow(x,y,35,25,18,color);
        return(x:x,y:y-35);
    


    // draw a down-arrow at the specified letterNumber
    function drawDownArrowUnder(text,x,y,letterNumber,color)
        x+=calcMidX(text,x,letterNumber);
        drawArrow(x,y,-22,-12,-5,color);
        return(x:x,y:y+22);
    

    // draw an up-arrow at the specified letterNumber
    function drawUpArrowUnder(text,x,y,letterNumber,color)
        x+=calcMidX(text,x,letterNumber);
        drawArrow(x,y,-5,-15,-22,color);
        return(x:x,y:y+22);
    

    function temporaryConnector(aConnector,color)
        var pt1=aConnector[0];
        var pt2=aConnector[aConnector.length-1];
        ctx.beginPath();
        ctx.moveTo(pt1.x,pt1.y);
        ctx.lineTo(pt2.x+2,pt2.y);
        ctx.strokeStyle=color;
        ctx.lineWidth=3;
        ctx.stroke();
    


); // end $(function());
</script>

</head>

<body>
    <p>Red arrow shows start</p>
    <p>Green arrow shows end</p>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

从 OP 编辑​​:如果有人感兴趣,这是我最终使用的最后一个小提琴:http://jsfiddle.net/53mQD/2/我取出红色箭头并用线条替换它们.所有功劳归于 markE。

【讨论】:

这很酷!我的目标是明天玩这个。一旦我有机会实施它,我会将其标记为解决方案。非常感谢! 我对一无所知,但经过一番研究后,似乎直线可以替换为圆弧(html5canvastutorials.com/tutorials/html5-canvas-arcs),二次曲线:context.quadraticCurveTo(288, 0, 388, 150);(html5canvastutorials.com/tutorials/… ),或贝塞尔曲线:context.bezierCurveTo(140, 10, 388, 10, 388, 170); (html5canvastutorials.com/tutorials/html5-canvas-bezier-curves)。关于从我的原始帖子中复制图像中的弯曲箭头效果有什么想法吗? 曲线的好处是它们看起来更“有机”。曲线的缺点是它们更复杂,因为必须计算控制点。曲线比直线占用更多空间。用曲线连接两个不同的短语(如插图底部连接器和中间右连接器中的连接器)将需要复合曲线,而这要构建起来要困难得多。这是一个使用曲线的小提琴:jsfiddle.net/m1erickson/53mQD 你是个天才!我只能投票一次,但如果可以的话,我的投票数会是 10。我现在需要做的就是不要在“起点”上向上或向下箭头。就像用从 5 向上(以及从 3 向下)的线替换箭头一样,但我会尝试从这里弄乱它。谢谢你的一切!

以上是关于将箭头“映射”到字符的主要内容,如果未能解决你的问题,请参考以下文章

SVG 标记方向箭头出现在 DOM 中,但标记本身不可见

林间空地键盘(转义,箭头)加速器

在 vimrc 中映射 <esc> 会导致奇怪的箭头行为

拖放功能和箭头图

如何在球拍中将左右箭头写为字符?

防止向下箭头或向上箭头更新 MS Access 中的组合框