Raphaeljs 方形模拟时钟

Square Analog Clock with Raphaeljs

我正在尝试用 Raphael JS 创建一种方形时钟,而不是 12 位数字,我的有 8 位数字。我在这个页面上找到了一个很好的圆形时钟示例; Emanuele Feronato

我想以此为基础创建我的时钟,但我在将数字破折号与其位置对齐时遇到了问题。对于第一轮,基本示例使用一些余弦和正弦来计算它们的位置。但是在第一个正方形上,我希望所有的破折号都对齐,这样它们就会碰到正方形的边界。

目标是这样的;

我想知道计算正方形的这些破折号位置的最简单和最好的方法是什么?是否也有一个干净的数学解决方案,如方块时钟中使用的那样?

这是我当前模板的fiddle; fiddle

这也是我当前的模板;

function draw_square_clock(svgId) {
  canvas = Raphael(svgId, 200, 200);
  var clock = canvas.rect(3, 3, 194, 194);
  clock.attr({
    "fill": "#ffffff",
    "stroke": "#000000",
    "stroke-width": "4"
  });
  var hour_sign;
  var text_sign;
  for (i = 0.0; i < 12; i = i + 1.5) {
    //How am I going to calculate these four values to align hour signs to the edges of square
    var start_x = 100 + Math.round(80 * Math.cos(30 * i * Math.PI / 180));
    var start_y = 100 + Math.round(80 * Math.sin(30 * i * Math.PI / 180));
    var end_x = 100 + Math.round(90 * Math.cos(30 * i * Math.PI / 180));
    var end_y = 100 + Math.round(90 * Math.sin(30 * i * Math.PI / 180));

    hour_sign = canvas.path("M" + start_x + " " + start_y + "L" + end_x + " " + end_y);
    hour_sign.attr({
      "stroke-width": "6"
    });
    hour_sign.transform("t0,0 s2");

  }

  hour_hand = canvas.path("M100 100L100 50");
  hour_hand.attr({
    stroke: "#000000",
    "stroke-width": 6
  });
  var pin = canvas.circle(100, 100, 8);
  pin.attr("fill", "#000000");
}



$(document).ready(function() {
  draw_square_clock('clock_id');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js"></script>

<div id="clock_id"></div>

数学上:

计算角刻度的长度:

// length of tick a 0 degrees
var tickLengthAt0=30;

// calculate length of corner tick
var cornerTickLength=Math.sqrt(2*(tickLengthAt0*tickLengthAt0));

使用三角函数计算每个刻度线段:

var PI=Math.PI;
var cx=150;
var cy=150;
var width=200;
var height=200;

function calcTickPoints(x0,y0,length,angle){
    x1=x0+length*Math.cos(angle);
    y1=y0+length*Math.sin(angle);
    return({ x0:x0, y0:y0, x1:x1, y1:y1 });
}

// Use calcTickPoints to calc the points of each tick

// top-right
var TR=calcTickPoints(cx+width/2,cy-height/2,cornerTickLength,PI*3/4);
// bottom-right
var BR=calcTickPoints(cx+width/2,cy+height/2,cornerTickLength,PI*5/4);
// bottom-left
var BL=calcTickPoints(cx-width/2,cy+height/2,cornerTickLength,PI*7/4);
// top-left
var TL=calcTickPoints(cx-width/2,cy-height/2,cornerTickLength,PI*9/4);
// right
var R=calcTickPoints(cx+width/2,cy,tickLengthAt0,PI);
// bottom
var B=calcTickPoints(cx,cy+height/2,tickLengthAt0,PI*3/2);
// left
var L=calcTickPoints(cx-width/2,cy,tickLengthAt0,PI*2);
// top
var T=calcTickPoints(cx,cy-height/2,tickLengthAt0,PI/2);

示例代码(在 Canvas 上绘制,但如果需要,您可以使用 SVG):

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var PI=Math.PI;
var PI2=PI*2;
var cx=150;
var cy=150;
var width=200;
var height=200;
var tickLengthAt0=30;
var cornerTickLength=Math.sqrt(2*(tickLengthAt0*tickLengthAt0));

drawFace();

function drawFace(){       
  // rect
  ctx.strokeRect(cx-width/2,cy-height/2,width,height);
  // top-right
  drawTick(cx+width/2,cy-height/2,cornerTickLength,PI*3/4);
  // bottom-right
  drawTick(cx+width/2,cy+height/2,cornerTickLength,PI*5/4);
  // bottom-left
  drawTick(cx-width/2,cy+height/2,cornerTickLength,PI*7/4);
  // top-left
  drawTick(cx-width/2,cy-height/2,cornerTickLength,PI*9/4);
  // right
  drawTick(cx+width/2,cy,tickLengthAt0,PI);
  // bottom
  drawTick(cx,cy+height/2,tickLengthAt0,PI*3/2);
  // left
  drawTick(cx-width/2,cy,tickLengthAt0,PI*2);
  // top
  drawTick(cx,cy-height/2,tickLengthAt0,PI/2);
}

function drawTick(x0,y0,length,angle){
  x1=x0+length*Math.cos(angle);
  y1=y0+length*Math.sin(angle);
  ctx.beginPath();
  ctx.moveTo(x0,y0);
  ctx.lineTo(x1,y1);
  ctx.stroke();
  return({ x0:x0, y0:y0, x1:x1, y1:y1 });
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>