修复旋转元素内的文本方向
Fix text-orientation inside rotated element
我正在尝试用 HTML、CSS 和 JS 构建一个动画时钟,我已经设法将小时定位在正确的位置,但现在数字不是直线的。
我一直在研究 text-orientation
属性 并尝试使用 text-orientation: auto
和 text-orientation: mixed
,但 none 似乎有效。
到目前为止我的时钟是这样的:
const clock = document.getElementById('clock');
const numbers = clock.children;
for (let i = 0; i < 12; i++) {
numbers[i].style.transform = 'translate(0, -50%) rotate(' + (90 + i * 30) + 'deg)';
}
const hours = document.getElementById('hours');
const minutes = document.getElementById('minutes');
const seconds = document.getElementById('seconds');
setInterval(function() {
const time = new Date();
hours.style.transform = 'translate(0, -50%) rotate(' + (time.getHours() % 12 * 30 - 90) + 'deg)';
minutes.style.transform = 'translate(0, -50%) rotate(' + (time.getMinutes() * 6 - 90) + 'deg)';
seconds.style.transform = 'translate(0, -50%) rotate(' + (time.getSeconds() * 6 - 90) + 'deg)';
});
#clock {
width: 200px;
height: 200px;
border: 3px solid black;
border-radius: 50%;
position: relative;
}
.hour{
position: absolute;
top: 50%;
left: 0;
width: 100%;
text-orientation: mixed;
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
}
#hours {
border-bottom: 3px solid black;
width: 25%;
}
#minutes {
border-bottom: 2px solid black;
width: 35%;
}
#seconds {
border-bottom: 1px solid red;
width: 45%;
}
<div id="clock">
<div class="hour">- 12</div>
<div class="hour">- 1</div>
<div class="hour">- 2</div>
<div class="hour">- 3</div>
<div class="hour">- 4</div>
<div class="hour">- 5</div>
<div class="hour">- 6</div>
<div class="hour">- 7</div>
<div class="hour">- 8</div>
<div class="hour">- 9</div>
<div class="hour">- 10</div>
<div class="hour">- 11</div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
您不能使用 text-orientation
做到这一点。 属性 更多的是关于阅读方向而不是设计或布局,并且仅用于垂直模式的文本,如 MDN 中所述:
The text-orientation CSS property sets the orientation of the text characters in a line. It only affects text in vertical mode (when writing-mode is not horizontal-tb). It is useful for controlling the display of languages that use vertical script, and also for making vertical table headers.
相反,您需要将小时数包装在固定 width
的单独 div
或 span
中以获得更一致的外观,并应用相反的 transform: rotate(...)
到那个。
此外,您可能希望逐步旋转分钟和小时手柄。也就是说,如果它是 12:30
,那么小时的句柄应该在 12 和 1 之间。
你应该在 setInterval
中添加一个 delay
。现在它被调用的次数比需要的多(每秒一次)来更新句柄。
const hoursHandle = document.getElementById('hours');
const minutesHandle = document.getElementById('minutes');
const secondsHandle = document.getElementById('seconds');
// Use querySelectorAll and avoid iterating over the handles by mistake:
document.querySelectorAll('.hour').forEach((child, i) => {
const angle = 90 + i * 30;
child.style.transform = `translate(0, -50%) rotate(${ angle }deg)`;
child.children[0].style.transform = `rotate(${ -angle }deg)`;
});
function updateHandles() {
// With requestAnimationFrame we avoid forcing a repaint:
requestAnimationFrame(() => {
const time = new Date();
const seconds = time.getSeconds();
const minutes = time.getMinutes();
const hours = time.getHours() % 12;
const secondsAngle = -90 + 6 * seconds;
const minutesAngle = -90 + 6 * (minutes + seconds/60);
const hoursAngle = -90 + 30 * (hours + minutes/60 + seconds/3600);
hoursHandle.style.transform = `translate(0, -50%) rotate(${ hoursAngle }deg)`;
minutesHandle.style.transform = `translate(0, -50%) rotate(${ minutesAngle }deg)`;
secondsHandle.style.transform = `translate(0, -50%) rotate(${ secondsAngle }deg)`;
});
}
updateHandles();
setInterval(updateHandles, 250);
body {
font-family: monospace;
margin: 0;
}
#clock {
margin: 16px auto;
width: 256px;
height: 256px;
border-radius: 50%;
position: relative;
box-shadow: 0 0 64px rgba(0, 0, 0, .125);
}
.hour {
position: absolute;
top: 50%;
left: 0;
width: 100%;
font-weight: bold;
}
/*
Add the marks with CSS rather than using a dash:
*/
.hour::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 4px;
border-top: 1px solid black;
transform: translate(0, -50%);
}
.hour > div {
width: 32px;
padding: 0 8px;
display: flex;
justify-content: center;
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
}
#hours {
background: rgba(0, 0, 0, .5);
height: 6px;
right: 64px;
}
#minutes {
background: rgba(0, 0, 0, .25);
height: 4px;
right: 48px;
}
#seconds {
background: red;
height: 2px;
right: 16px;
}
#seconds::before,
#seconds::after {
content: '';
position: absolute;
background: red;
}
#seconds::before {
top: 0;
left: -24px;
width: 24px;
height: 100%;
}
#seconds::after {
top: 50%;
left: 0;
width: 8px;
height: 8px;
transform: translate(-50%, -50%);
border-radius: 100%;
}
<div id="clock">
<div class="hour"><div>12</div></div>
<div class="hour"><div>1</div></div>
<div class="hour"><div>2</div></div>
<div class="hour"><div>3</div></div>
<div class="hour"><div>4</div></div>
<div class="hour"><div>5</div></div>
<div class="hour"><div>6</div></div>
<div class="hour"><div>7</div></div>
<div class="hour"><div>8</div></div>
<div class="hour"><div>9</div></div>
<div class="hour"><div>10</div></div>
<div class="hour"><div>11</div></div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
因为今天是守望者最后一集的发布...:[=26=]
const clock = document.getElementById('clock');
const hoursHandle = document.getElementById('hours');
const minutesHandle = document.getElementById('minutes');
const secondsHandle = document.getElementById('seconds');
// Use querySelectorAll and avoid iterating over the handles by mistake:
document.querySelectorAll('.hour').forEach((child, i) => {
const angle = 90 + i * 30;
child.style.transform = `translate(0, -50%) rotate(${ angle }deg)`;
});
// Add 60 marks around the block:
for (let i = 0; i < 60; ++i) {
const mark = document.createElement('DIV');
mark.className = 'mark';
mark.style.transform = `rotate(${ i * 6 }deg)`;
clock.appendChild(mark);
}
function updateHandles() {
// With requestAnimationFrame we avoid forcing a repaint:
requestAnimationFrame(() => {
const time = new Date();
const seconds = time.getSeconds();
const minutes = time.getMinutes();
const hours = time.getHours() % 12;
const secondsAngle = -90 + 6 * seconds;
const minutesAngle = -90 + 6 * (minutes + seconds/60);
const hoursAngle = -90 + 30 * (hours + minutes/60 + seconds/3600);
hoursHandle.style.transform = `translate(0, -50%) rotate(${ hoursAngle }deg)`;
minutesHandle.style.transform = `translate(0, -50%) rotate(${ minutesAngle }deg)`;
secondsHandle.style.transform = `translate(0, -50%) rotate(${ secondsAngle }deg)`;
});
}
updateHandles();
setInterval(updateHandles, 250);
body {
font-family: monospace;
margin: 0;
background: black;
}
body::before,
body::after {
content: '';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
}
body::before {
background: linear-gradient(-135deg, rgba(0, 0, 255, .125), transparent);
}
body::after {
background: linear-gradient(45deg, rgba(255, 0, 0, .125), transparent);
z-index: 1;
}
#clock {
margin: 16px auto;
width: 256px;
height: 256px;
border-radius: 50%;
position: relative;
background: #fbdf27;
text-shadow: 0 0 1px black;
}
.hour {
position: absolute;
top: 50%;
left: 0;
width: 50%;
font-weight: bold;
font-size: 10px;
transform-origin: right center;
background: #fbdf27;
z-index: 1;
}
.hour > div {
width: 16px;
display: flex;
justify-content: center;
transform: rotate(-90deg);
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
background: blue;
z-index: 100;
mix-blend-mode: color-burn;
}
#hours {
height: 6px;
right: 64px;
}
#minutes {
height: 4px;
right: 48px;
}
#seconds {
height: 2px;
right: 16px;
}
#seconds::before,
#seconds::after {
content: '';
position: absolute;
background: blue;
}
#seconds::before {
top: 0;
left: -24px;
width: 24px;
height: 100%;
mix-blend-mode: color-burn;
}
#seconds::after {
top: 50%;
left: 0;
width: 8px;
height: 8px;
transform: translate(-50%, -50%);
border-radius: 100%;
}
#title {
position: absolute;
top: 192px;
left: 50%;
width: 272px;
color: #fbdf27;
background: black;
font-size: 62px;
line-height: 40px;
text-align: center;
transform: translate(-50%, -50%);
z-index: 50;
}
.mark {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 1px;
transform: translate(-50%, 0);
}
.mark::before {
content: '';
position: absolute;
top: 6px;
right: 0;
left: 0;
height: 4px;
background: black;
}
<div id="title">WATCHMEN</div>
<div id="clock">
<div class="hour"><div>XII</div></div>
<div class="hour"><div>I</div></div>
<div class="hour"><div>II</div></div>
<div class="hour"><div>III</div></div>
<div class="hour"><div>IV</div></div>
<div class="hour"><div>V</div></div>
<div class="hour"><div>VI</div></div>
<div class="hour"><div>VII</div></div>
<div class="hour"><div>VIII</div></div>
<div class="hour"><div>IX</div></div>
<div class="hour"><div>X</div></div>
<div class="hour"><div>XI</div></div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
您可以通过仅考虑翻译和 cos/sin 公式来进行不同的计算。
值.8
将定义距中心的距离,您可以随意调整。不要忘记 cos/sin 取一个弧度角,这就是为什么我们必须乘以`Math.PI/180.
我考虑了小线条的背景技巧:
const clock = document.getElementById('clock');
const numbers = clock.children;
const h = 0.8 * (clock.offsetHeight/2);
for (let i = 0; i < 12; i++) {
numbers[i].style.transform =
'translate(-50%, -50%) translate('
+ (-h*Math.cos((90 + i * 30)*Math.PI/180)) + 'px,'
+ (-h*Math.sin((90 + i * 30)*Math.PI/180)) + 'px)';
}
const hours = document.getElementById('hours');
const minutes = document.getElementById('minutes');
const seconds = document.getElementById('seconds');
setInterval(function() {
const time = new Date();
hours.style.transform = 'rotate(' + (time.getHours() % 12 * 30 - 90) + 'deg)';
minutes.style.transform = 'rotate(' + (time.getMinutes() * 6 - 90) + 'deg)';
seconds.style.transform = 'rotate(' + (time.getSeconds() * 6 - 90) + 'deg)';
});
#clock {
width: 200px;
height: 200px;
border: 3px solid black;
padding:5px; /* Control the length of the lines*/
box-sizing:border-box;
border-radius: 50%;
position: relative;
background:
linear-gradient(#fff,#fff) content-box,
linear-gradient(#000,#000) center/100% 2px,
linear-gradient(#000,#000) center/2px 100%,
linear-gradient(30deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(-30deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(60deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(-60deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)) ;
background-repeat:no-repeat;
}
.hour,
.handle{
position: absolute;
top: 50%;
left: 50%;
transform-origin: left;
}
#hours {
border-bottom: 4px solid black;
margin-top:-2px;
width: 25%;
}
#minutes {
border-bottom: 2px solid black;
margin-top:-1px;
width: 35%;
}
#seconds {
border-bottom: 1px solid red;
width: 45%;
}
<div id="clock">
<div class="hour"> 12</div>
<div class="hour"> 1</div>
<div class="hour"> 2</div>
<div class="hour"> 3</div>
<div class="hour"> 4</div>
<div class="hour"> 5</div>
<div class="hour"> 6</div>
<div class="hour"> 7</div>
<div class="hour"> 8</div>
<div class="hour"> 9</div>
<div class="hour"> 10</div>
<div class="hour"> 11</div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
我正在尝试用 HTML、CSS 和 JS 构建一个动画时钟,我已经设法将小时定位在正确的位置,但现在数字不是直线的。
我一直在研究 text-orientation
属性 并尝试使用 text-orientation: auto
和 text-orientation: mixed
,但 none 似乎有效。
到目前为止我的时钟是这样的:
const clock = document.getElementById('clock');
const numbers = clock.children;
for (let i = 0; i < 12; i++) {
numbers[i].style.transform = 'translate(0, -50%) rotate(' + (90 + i * 30) + 'deg)';
}
const hours = document.getElementById('hours');
const minutes = document.getElementById('minutes');
const seconds = document.getElementById('seconds');
setInterval(function() {
const time = new Date();
hours.style.transform = 'translate(0, -50%) rotate(' + (time.getHours() % 12 * 30 - 90) + 'deg)';
minutes.style.transform = 'translate(0, -50%) rotate(' + (time.getMinutes() * 6 - 90) + 'deg)';
seconds.style.transform = 'translate(0, -50%) rotate(' + (time.getSeconds() * 6 - 90) + 'deg)';
});
#clock {
width: 200px;
height: 200px;
border: 3px solid black;
border-radius: 50%;
position: relative;
}
.hour{
position: absolute;
top: 50%;
left: 0;
width: 100%;
text-orientation: mixed;
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
}
#hours {
border-bottom: 3px solid black;
width: 25%;
}
#minutes {
border-bottom: 2px solid black;
width: 35%;
}
#seconds {
border-bottom: 1px solid red;
width: 45%;
}
<div id="clock">
<div class="hour">- 12</div>
<div class="hour">- 1</div>
<div class="hour">- 2</div>
<div class="hour">- 3</div>
<div class="hour">- 4</div>
<div class="hour">- 5</div>
<div class="hour">- 6</div>
<div class="hour">- 7</div>
<div class="hour">- 8</div>
<div class="hour">- 9</div>
<div class="hour">- 10</div>
<div class="hour">- 11</div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
您不能使用 text-orientation
做到这一点。 属性 更多的是关于阅读方向而不是设计或布局,并且仅用于垂直模式的文本,如 MDN 中所述:
The text-orientation CSS property sets the orientation of the text characters in a line. It only affects text in vertical mode (when writing-mode is not horizontal-tb). It is useful for controlling the display of languages that use vertical script, and also for making vertical table headers.
相反,您需要将小时数包装在固定 width
的单独 div
或 span
中以获得更一致的外观,并应用相反的 transform: rotate(...)
到那个。
此外,您可能希望逐步旋转分钟和小时手柄。也就是说,如果它是 12:30
,那么小时的句柄应该在 12 和 1 之间。
你应该在 setInterval
中添加一个 delay
。现在它被调用的次数比需要的多(每秒一次)来更新句柄。
const hoursHandle = document.getElementById('hours');
const minutesHandle = document.getElementById('minutes');
const secondsHandle = document.getElementById('seconds');
// Use querySelectorAll and avoid iterating over the handles by mistake:
document.querySelectorAll('.hour').forEach((child, i) => {
const angle = 90 + i * 30;
child.style.transform = `translate(0, -50%) rotate(${ angle }deg)`;
child.children[0].style.transform = `rotate(${ -angle }deg)`;
});
function updateHandles() {
// With requestAnimationFrame we avoid forcing a repaint:
requestAnimationFrame(() => {
const time = new Date();
const seconds = time.getSeconds();
const minutes = time.getMinutes();
const hours = time.getHours() % 12;
const secondsAngle = -90 + 6 * seconds;
const minutesAngle = -90 + 6 * (minutes + seconds/60);
const hoursAngle = -90 + 30 * (hours + minutes/60 + seconds/3600);
hoursHandle.style.transform = `translate(0, -50%) rotate(${ hoursAngle }deg)`;
minutesHandle.style.transform = `translate(0, -50%) rotate(${ minutesAngle }deg)`;
secondsHandle.style.transform = `translate(0, -50%) rotate(${ secondsAngle }deg)`;
});
}
updateHandles();
setInterval(updateHandles, 250);
body {
font-family: monospace;
margin: 0;
}
#clock {
margin: 16px auto;
width: 256px;
height: 256px;
border-radius: 50%;
position: relative;
box-shadow: 0 0 64px rgba(0, 0, 0, .125);
}
.hour {
position: absolute;
top: 50%;
left: 0;
width: 100%;
font-weight: bold;
}
/*
Add the marks with CSS rather than using a dash:
*/
.hour::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 4px;
border-top: 1px solid black;
transform: translate(0, -50%);
}
.hour > div {
width: 32px;
padding: 0 8px;
display: flex;
justify-content: center;
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
}
#hours {
background: rgba(0, 0, 0, .5);
height: 6px;
right: 64px;
}
#minutes {
background: rgba(0, 0, 0, .25);
height: 4px;
right: 48px;
}
#seconds {
background: red;
height: 2px;
right: 16px;
}
#seconds::before,
#seconds::after {
content: '';
position: absolute;
background: red;
}
#seconds::before {
top: 0;
left: -24px;
width: 24px;
height: 100%;
}
#seconds::after {
top: 50%;
left: 0;
width: 8px;
height: 8px;
transform: translate(-50%, -50%);
border-radius: 100%;
}
<div id="clock">
<div class="hour"><div>12</div></div>
<div class="hour"><div>1</div></div>
<div class="hour"><div>2</div></div>
<div class="hour"><div>3</div></div>
<div class="hour"><div>4</div></div>
<div class="hour"><div>5</div></div>
<div class="hour"><div>6</div></div>
<div class="hour"><div>7</div></div>
<div class="hour"><div>8</div></div>
<div class="hour"><div>9</div></div>
<div class="hour"><div>10</div></div>
<div class="hour"><div>11</div></div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
因为今天是守望者最后一集的发布...:[=26=]
const clock = document.getElementById('clock');
const hoursHandle = document.getElementById('hours');
const minutesHandle = document.getElementById('minutes');
const secondsHandle = document.getElementById('seconds');
// Use querySelectorAll and avoid iterating over the handles by mistake:
document.querySelectorAll('.hour').forEach((child, i) => {
const angle = 90 + i * 30;
child.style.transform = `translate(0, -50%) rotate(${ angle }deg)`;
});
// Add 60 marks around the block:
for (let i = 0; i < 60; ++i) {
const mark = document.createElement('DIV');
mark.className = 'mark';
mark.style.transform = `rotate(${ i * 6 }deg)`;
clock.appendChild(mark);
}
function updateHandles() {
// With requestAnimationFrame we avoid forcing a repaint:
requestAnimationFrame(() => {
const time = new Date();
const seconds = time.getSeconds();
const minutes = time.getMinutes();
const hours = time.getHours() % 12;
const secondsAngle = -90 + 6 * seconds;
const minutesAngle = -90 + 6 * (minutes + seconds/60);
const hoursAngle = -90 + 30 * (hours + minutes/60 + seconds/3600);
hoursHandle.style.transform = `translate(0, -50%) rotate(${ hoursAngle }deg)`;
minutesHandle.style.transform = `translate(0, -50%) rotate(${ minutesAngle }deg)`;
secondsHandle.style.transform = `translate(0, -50%) rotate(${ secondsAngle }deg)`;
});
}
updateHandles();
setInterval(updateHandles, 250);
body {
font-family: monospace;
margin: 0;
background: black;
}
body::before,
body::after {
content: '';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
}
body::before {
background: linear-gradient(-135deg, rgba(0, 0, 255, .125), transparent);
}
body::after {
background: linear-gradient(45deg, rgba(255, 0, 0, .125), transparent);
z-index: 1;
}
#clock {
margin: 16px auto;
width: 256px;
height: 256px;
border-radius: 50%;
position: relative;
background: #fbdf27;
text-shadow: 0 0 1px black;
}
.hour {
position: absolute;
top: 50%;
left: 0;
width: 50%;
font-weight: bold;
font-size: 10px;
transform-origin: right center;
background: #fbdf27;
z-index: 1;
}
.hour > div {
width: 16px;
display: flex;
justify-content: center;
transform: rotate(-90deg);
}
.handle {
position: absolute;
top: 50%;
left: 50%;
transform-origin: left center;
background: blue;
z-index: 100;
mix-blend-mode: color-burn;
}
#hours {
height: 6px;
right: 64px;
}
#minutes {
height: 4px;
right: 48px;
}
#seconds {
height: 2px;
right: 16px;
}
#seconds::before,
#seconds::after {
content: '';
position: absolute;
background: blue;
}
#seconds::before {
top: 0;
left: -24px;
width: 24px;
height: 100%;
mix-blend-mode: color-burn;
}
#seconds::after {
top: 50%;
left: 0;
width: 8px;
height: 8px;
transform: translate(-50%, -50%);
border-radius: 100%;
}
#title {
position: absolute;
top: 192px;
left: 50%;
width: 272px;
color: #fbdf27;
background: black;
font-size: 62px;
line-height: 40px;
text-align: center;
transform: translate(-50%, -50%);
z-index: 50;
}
.mark {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 1px;
transform: translate(-50%, 0);
}
.mark::before {
content: '';
position: absolute;
top: 6px;
right: 0;
left: 0;
height: 4px;
background: black;
}
<div id="title">WATCHMEN</div>
<div id="clock">
<div class="hour"><div>XII</div></div>
<div class="hour"><div>I</div></div>
<div class="hour"><div>II</div></div>
<div class="hour"><div>III</div></div>
<div class="hour"><div>IV</div></div>
<div class="hour"><div>V</div></div>
<div class="hour"><div>VI</div></div>
<div class="hour"><div>VII</div></div>
<div class="hour"><div>VIII</div></div>
<div class="hour"><div>IX</div></div>
<div class="hour"><div>X</div></div>
<div class="hour"><div>XI</div></div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>
您可以通过仅考虑翻译和 cos/sin 公式来进行不同的计算。
值.8
将定义距中心的距离,您可以随意调整。不要忘记 cos/sin 取一个弧度角,这就是为什么我们必须乘以`Math.PI/180.
我考虑了小线条的背景技巧:
const clock = document.getElementById('clock');
const numbers = clock.children;
const h = 0.8 * (clock.offsetHeight/2);
for (let i = 0; i < 12; i++) {
numbers[i].style.transform =
'translate(-50%, -50%) translate('
+ (-h*Math.cos((90 + i * 30)*Math.PI/180)) + 'px,'
+ (-h*Math.sin((90 + i * 30)*Math.PI/180)) + 'px)';
}
const hours = document.getElementById('hours');
const minutes = document.getElementById('minutes');
const seconds = document.getElementById('seconds');
setInterval(function() {
const time = new Date();
hours.style.transform = 'rotate(' + (time.getHours() % 12 * 30 - 90) + 'deg)';
minutes.style.transform = 'rotate(' + (time.getMinutes() * 6 - 90) + 'deg)';
seconds.style.transform = 'rotate(' + (time.getSeconds() * 6 - 90) + 'deg)';
});
#clock {
width: 200px;
height: 200px;
border: 3px solid black;
padding:5px; /* Control the length of the lines*/
box-sizing:border-box;
border-radius: 50%;
position: relative;
background:
linear-gradient(#fff,#fff) content-box,
linear-gradient(#000,#000) center/100% 2px,
linear-gradient(#000,#000) center/2px 100%,
linear-gradient(30deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(-30deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(60deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)),
linear-gradient(-60deg,
transparent calc(50% - 1px),
#000 calc(50% - 1px) calc(50% + 1px),
transparent calc(50% + 1px)) ;
background-repeat:no-repeat;
}
.hour,
.handle{
position: absolute;
top: 50%;
left: 50%;
transform-origin: left;
}
#hours {
border-bottom: 4px solid black;
margin-top:-2px;
width: 25%;
}
#minutes {
border-bottom: 2px solid black;
margin-top:-1px;
width: 35%;
}
#seconds {
border-bottom: 1px solid red;
width: 45%;
}
<div id="clock">
<div class="hour"> 12</div>
<div class="hour"> 1</div>
<div class="hour"> 2</div>
<div class="hour"> 3</div>
<div class="hour"> 4</div>
<div class="hour"> 5</div>
<div class="hour"> 6</div>
<div class="hour"> 7</div>
<div class="hour"> 8</div>
<div class="hour"> 9</div>
<div class="hour"> 10</div>
<div class="hour"> 11</div>
<div class="handle" id="hours"></div>
<div class="handle" id="minutes"></div>
<div class="handle" id="seconds"></div>
</div>