SVG 月相
SVG Moon Phases
对于较大的项目,我想在悬停日期添加月相。我找到了计算月相的javascript,我还找到了@Alexandr_TT在.
发布的SVG月相解决方案
javascript月相的数学计算:
function getMoonPhase(year, month, day) {
var c = e = jd = b = 0;
if (month < 3) {
year--;
month += 12;
}
++month;
c = 365.25 * year;
e = 30.6 * month;
jd = c + e + day - 694039.09; //jd is total days elapsed
jd /= 29.5305882; //divide by the moon cycle
b = parseInt(jd); //int(jd) -> b, take integer part of jd
jd -= b; //subtract integer part to leave fractional part of original jd
b = Math.round(jd * 8); //scale fraction from 0-8 and round
if (b >= 8 ) {
b = 0; //0 and 8 are the same so turn 8 into 0
}
// 0 => New Moon
// 1 => Waxing Crescent Moon
// 2 => Quarter Moon
// 3 => Waxing Gibbous Moon
// 4 => Full Moon
// 5 => Waning Gibbous Moon
// 6 => Last Quarter Moon
// 7 => Waning Crescent Moon
return b;
}
Alexandr 的 SVG 是一个动画,所以我的问题是 svg 可以是基于 javascript 的输出值的快照吗?
我当然可以为 8 个阶段中的每个阶段生成单独的静态 SVG。我也可以尝试修改我在 Github at https://github.com/tingletech/moon-phase 上找到的解决方案,但我被 Alexandr 的 SVC 代码所吸引,因为它很小。
我的目标是输出 javascript 的数值,然后以实现目标所需的最少代码量呈现视觉上驱动的 SVG。
我是 SVG 的菜鸟。 github 上的解决方案使用了 SVG 中 path 的 arc 属性,看起来 Alexandr 使用的是两个相交的圆。根据我从javascript?
得到的值是否可以有效停止动画
提前致谢。
你好,我有一个这样的工作副本:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Moon Phase Today</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 73 73" >
<defs>
<radialGradient id="RadialGrad" fx="50%" fy="50%" r="65%" spreadMethod="pad">
<stop offset="0%" stop-color="#E7D68C" stop-opacity="1"/>
<stop offset="100%" stop-color="#FFFEED" stop-opacity="1" />
</radialGradient>
</defs>
<rect width="100%" height="100%" />
<g transform="rotate(-20 35.5 35.5)">
<circle cx="35.5" cy="35.5" r="35" stroke="none" fill="url(#RadialGrad)" />
<circle id='layoverCircle' cx="35.5" cy="35.5" r="35" stroke="none" fill="black" />
<rect id="layoverRectangle" style="display: none" width="100%" height="100%" />
<!-- <animate id="youngMoon" attributeName="cx" values="35.5;-35.5;" begin="1s;oldMoon.end+1s" dur="10s" fill="freeze" /> -->
<!-- <animate id="oldMoon" attributeName="cx" values="105;35.5;" begin="youngMoon.end+1s" dur="10s" fill="freeze" /> -->
<!-- </circle> -->
</g>
</svg>
<script type="text/javascript">
function setState(value, showCircle, showRect) {
let circle = document.getElementById('layoverCircle');
let rect = document.getElementById('layoverRectangle');
circle.style.display = showCircle ? "block" : "none";
rect.style.display = showRect ? "block" : "none";
if (showRect) rect.style.transform = value
if (showCircle) circle.setAttribute("cx", value);
}
function getMoonPhase(year, month, day) {
var c = e = jd = b = 0;
if (month < 3) {
year--;
month += 12;
}
++month;
c = 365.25 * year;
e = 30.6 * month;
jd = c + e + day - 694039.09; //jd is total days elapsed
jd /= 29.5305882; //divide by the moon cycle
b = parseInt(jd); //int(jd) -> b, take integer part of jd
jd -= b; //subtract integer part to leave fractional part of original jd
b = Math.round(jd * 8); //scale fraction from 0-8 and round
if (b >= 8 ) {
b = 0; //0 and 8 are the same so turn 8 into 0
}
// 0 => New Moon 37.5 [show circle, hide rect]
// 1 => Waxing Crescent Moon 50.5 [show circle, hide rect]
// 2 => Quarter Moon //translateX(50%), [display rect, hide circle]
// 3 => Waxing Gibbous Moon 70.5 [show circle, hide rect]
// 4 => Full Moon [hide circle and rect]
// 5 => Waning Gibbous Moon, -15.5 [show circle, hide rect]
// 6 => Last Quarter Moon //transform: translateX(-50%) [display rect, hide circle]
// 7 => Waning Crescent Moon 30.5 [show circle, hide rect]
return b;
}
let d = new Date();
let i = 0;
let callback = function () {
let phase = getMoonPhase(d.getFullYear(), d.getMonth()+1, d.getDate() + i)
i += 4
if (phase == 0) setState(37.5, true, false);
if (phase == 1) setState(50.5, true, false);
if (phase == 2) setState("translateX(50%)", false, true);
if (phase == 3) setState(70.5 , true, false);
if (phase == 4) setState(NaN , false, false);
if (phase == 5) setState(-15.5, true, false);
if (phase == 6) setState("translateX(-50%)", false, true);
if (phase == 7) setState(30.5 , true, false);
setTimeout(callback, 1000);
};
callback();
</script>
</body>
</html>
setState 函数基本上就是您要找的。您还可以根据您的审美需求更改 setState 中的值。
对于较大的项目,我想在悬停日期添加月相。我找到了计算月相的javascript,我还找到了@Alexandr_TT在
javascript月相的数学计算:
function getMoonPhase(year, month, day) {
var c = e = jd = b = 0;
if (month < 3) {
year--;
month += 12;
}
++month;
c = 365.25 * year;
e = 30.6 * month;
jd = c + e + day - 694039.09; //jd is total days elapsed
jd /= 29.5305882; //divide by the moon cycle
b = parseInt(jd); //int(jd) -> b, take integer part of jd
jd -= b; //subtract integer part to leave fractional part of original jd
b = Math.round(jd * 8); //scale fraction from 0-8 and round
if (b >= 8 ) {
b = 0; //0 and 8 are the same so turn 8 into 0
}
// 0 => New Moon
// 1 => Waxing Crescent Moon
// 2 => Quarter Moon
// 3 => Waxing Gibbous Moon
// 4 => Full Moon
// 5 => Waning Gibbous Moon
// 6 => Last Quarter Moon
// 7 => Waning Crescent Moon
return b;
}
Alexandr 的 SVG 是一个动画,所以我的问题是 svg 可以是基于 javascript 的输出值的快照吗?
我当然可以为 8 个阶段中的每个阶段生成单独的静态 SVG。我也可以尝试修改我在 Github at https://github.com/tingletech/moon-phase 上找到的解决方案,但我被 Alexandr 的 SVC 代码所吸引,因为它很小。
我的目标是输出 javascript 的数值,然后以实现目标所需的最少代码量呈现视觉上驱动的 SVG。
我是 SVG 的菜鸟。 github 上的解决方案使用了 SVG 中 path 的 arc 属性,看起来 Alexandr 使用的是两个相交的圆。根据我从javascript?
得到的值是否可以有效停止动画提前致谢。
你好,我有一个这样的工作副本:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Moon Phase Today</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 73 73" >
<defs>
<radialGradient id="RadialGrad" fx="50%" fy="50%" r="65%" spreadMethod="pad">
<stop offset="0%" stop-color="#E7D68C" stop-opacity="1"/>
<stop offset="100%" stop-color="#FFFEED" stop-opacity="1" />
</radialGradient>
</defs>
<rect width="100%" height="100%" />
<g transform="rotate(-20 35.5 35.5)">
<circle cx="35.5" cy="35.5" r="35" stroke="none" fill="url(#RadialGrad)" />
<circle id='layoverCircle' cx="35.5" cy="35.5" r="35" stroke="none" fill="black" />
<rect id="layoverRectangle" style="display: none" width="100%" height="100%" />
<!-- <animate id="youngMoon" attributeName="cx" values="35.5;-35.5;" begin="1s;oldMoon.end+1s" dur="10s" fill="freeze" /> -->
<!-- <animate id="oldMoon" attributeName="cx" values="105;35.5;" begin="youngMoon.end+1s" dur="10s" fill="freeze" /> -->
<!-- </circle> -->
</g>
</svg>
<script type="text/javascript">
function setState(value, showCircle, showRect) {
let circle = document.getElementById('layoverCircle');
let rect = document.getElementById('layoverRectangle');
circle.style.display = showCircle ? "block" : "none";
rect.style.display = showRect ? "block" : "none";
if (showRect) rect.style.transform = value
if (showCircle) circle.setAttribute("cx", value);
}
function getMoonPhase(year, month, day) {
var c = e = jd = b = 0;
if (month < 3) {
year--;
month += 12;
}
++month;
c = 365.25 * year;
e = 30.6 * month;
jd = c + e + day - 694039.09; //jd is total days elapsed
jd /= 29.5305882; //divide by the moon cycle
b = parseInt(jd); //int(jd) -> b, take integer part of jd
jd -= b; //subtract integer part to leave fractional part of original jd
b = Math.round(jd * 8); //scale fraction from 0-8 and round
if (b >= 8 ) {
b = 0; //0 and 8 are the same so turn 8 into 0
}
// 0 => New Moon 37.5 [show circle, hide rect]
// 1 => Waxing Crescent Moon 50.5 [show circle, hide rect]
// 2 => Quarter Moon //translateX(50%), [display rect, hide circle]
// 3 => Waxing Gibbous Moon 70.5 [show circle, hide rect]
// 4 => Full Moon [hide circle and rect]
// 5 => Waning Gibbous Moon, -15.5 [show circle, hide rect]
// 6 => Last Quarter Moon //transform: translateX(-50%) [display rect, hide circle]
// 7 => Waning Crescent Moon 30.5 [show circle, hide rect]
return b;
}
let d = new Date();
let i = 0;
let callback = function () {
let phase = getMoonPhase(d.getFullYear(), d.getMonth()+1, d.getDate() + i)
i += 4
if (phase == 0) setState(37.5, true, false);
if (phase == 1) setState(50.5, true, false);
if (phase == 2) setState("translateX(50%)", false, true);
if (phase == 3) setState(70.5 , true, false);
if (phase == 4) setState(NaN , false, false);
if (phase == 5) setState(-15.5, true, false);
if (phase == 6) setState("translateX(-50%)", false, true);
if (phase == 7) setState(30.5 , true, false);
setTimeout(callback, 1000);
};
callback();
</script>
</body>
</html>
setState 函数基本上就是您要找的。您还可以根据您的审美需求更改 setState 中的值。