Vega-Lite 时钟(在 Vega-Lite 中使用定时器)

问题描述 投票:0回答:2

这是使用 Vega-lite 创建时钟的第一次尝试。欢迎回来提出一些关于如何改进这一点的想法。我只能使用 vega-embed 来刷新它。根据简单的变换过滤器显示或隐藏双手。我似乎无法对手使用 SVG 路径。有什么想法吗?

<!doctype html> 
<html> 
<head> 
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
</head>      
<body>
<div id="vis"></div>

<script type="text/javascript">
</script>

<script id="jsCode" type="text/javascript"> 

function generateSpec() {
const spec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Vega-lite clock",
"width": 500,
"height": 500, 
"data": {
"values": [
{"hour": "12", "min": "1", "minute": "01", "value": 1},
{"hour": "12", "min": "2", "minute": "02", "value": 1},
{"hour": "12", "min": "3", "minute": "03", "value": 1},
{"hour": "12", "min": "4", "minute": "04", "value": 1},
{"hour": "1", "min": "5", "minute": "05", "value": 1},
{"hour": "1", "min": "6", "minute": "06", "value": 1},
{"hour": "1", "min": "7", "minute": "07", "value": 1},
{"hour": "1", "min": "8", "minute": "08", "value": 1},
{"hour": "1", "min": "9", "minute": "09", "value": 1},
{"hour": "2", "min": "10", "minute": "10", "value": 1},
{"hour": "2", "min": "11", "minute": "11", "value": 1},
{"hour": "2", "min": "12", "minute": "12", "value": 1},
{"hour": "2", "min": "13", "minute": "13", "value": 1},
{"hour": "2", "min": "14", "minute": "14", "value": 1},
{"hour": "3", "min": "15", "minute": "15", "value": 1},
{"hour": "3", "min": "16", "minute": "16", "value": 1},
{"hour": "3", "min": "17", "minute": "17", "value": 1},
{"hour": "3", "min": "18", "minute": "18", "value": 1},
{"hour": "3", "min": "19", "minute": "19", "value": 1},
{"hour": "4", "min": "20", "minute": "20", "value": 1},
{"hour": "4", "min": "21", "minute": "21", "value": 1},
{"hour": "4", "min": "22", "minute": "22", "value": 1},
{"hour": "4", "min": "23", "minute": "23", "value": 1},
{"hour": "4", "min": "24", "minute": "24", "value": 1},
{"hour": "5", "min": "25", "minute": "25", "value": 1},
{"hour": "5", "min": "26", "minute": "26", "value": 1},
{"hour": "5", "min": "27", "minute": "27", "value": 1},
{"hour": "5", "min": "28", "minute": "28", "value": 1},
{"hour": "5", "min": "29", "minute": "29", "value": 1},
{"hour": "6", "min": "30", "minute": "30", "value": 1},
{"hour": "6", "min": "31", "minute": "31", "value": 1},
{"hour": "6", "min": "32", "minute": "32", "value": 1},
{"hour": "6", "min": "33", "minute": "33", "value": 1},
{"hour": "6", "min": "34", "minute": "34", "value": 1},
{"hour": "7", "min": "35", "minute": "35", "value": 1},
{"hour": "7", "min": "36", "minute": "36", "value": 1},
{"hour": "7", "min": "37", "minute": "37", "value": 1},
{"hour": "7", "min": "38", "minute": "38", "value": 1},
{"hour": "7", "min": "39", "minute": "39", "value": 1},
{"hour": "8", "min": "40", "minute": "40", "value": 1},
{"hour": "8", "min": "41", "minute": "41", "value": 1},
{"hour": "8", "min": "42", "minute": "42", "value": 1},
{"hour": "8", "min": "43", "minute": "43", "value": 1},
{"hour": "8", "min": "44", "minute": "44", "value": 1},
{"hour": "9", "min": "45", "minute": "45", "value": 1},
{"hour": "9", "min": "46", "minute": "46", "value": 1},
{"hour": "9", "min": "47", "minute": "47", "value": 1},
{"hour": "9", "min": "48", "minute": "48", "value": 1},
{"hour": "9", "min": "49", "minute": "49", "value": 1},
{"hour": "10", "min": "50", "minute": "50", "value": 1},
{"hour": "10", "min": "51", "minute": "51", "value": 1},
{"hour": "10", "min": "52", "minute": "52", "value": 1},
{"hour": "10", "min": "53", "minute": "53", "value": 1},
{"hour": "10", "min": "54", "minute": "54", "value": 1},
{"hour": "11", "min": "55", "minute": "55", "value": 1},
{"hour": "11", "min": "56", "minute": "56", "value": 1},
{"hour": "11", "min": "57", "minute": "57", "value": 1},
{"hour": "11", "min": "58", "minute": "58", "value": 1},
{"hour": "11", "min": "59", "minute": "59", "value": 1},
{"hour": "12", "min": "0", "minute": "60", "value": 1}
]
},
"transform": [
{"joinaggregate": [{"op": "sum", "field": "value", "as": "total"}]},
{
"sort": [{"field": "minute"}],
"window": [{"op": "sum", "field": "value", "as": "Cumulat"}],
"frame": [null, 0]
},
{
"calculate": "(360* ((datum.Cumulat) / datum.total))-90",
"as": "percentage"
}
],
"layer": [
{
"mark": {"type": "arc", "outerRadius": 365, "innerRadius": 275},
"encoding": {"color": {"value": "aliceblue"}}
},
{
"mark": {"type": "arc", "outerRadius": 278, "innerRadius": 275},
"encoding": {"color": {"value": "silver"}}
},
{
"mark": {
"type": "text",
"radius": 287,
"fontSize": 13,
"angle": {"expr": "datum.percentage"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"value": "—"},
"color": {"value": "silver"}
}
},
{
"transform": [
{
"filter": {
"field": "minute",
"oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
}
}
],
"mark": {
"type": "text",
"radius": 270,
"fontSize": 25,
"angle": {"expr": "datum.percentage"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"value": "⏴"},
"color": {"value": "black"}
}
},
{
"mark": {"type": "text", "radius": 305},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"field": "min", "type": "nominal"},
"color": {"value": "black"}
}
},
{
"transform": [
{
"filter": {
"field": "minute",
"oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
}
}
],
"mark": {
"type": "text",
"radius": 330,
"fontSize": 15,
"fontWeight": 800
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"field": "hour"},
"color": {"value": "black"}
}
},
{
"transform": [
{
"filter": {
"field": "minute",
"oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
}
}
],
"mark": {
"type": "text",
"radius": 352,
"fontSize": 12,
"fontWeight": 600,
"text": {"expr": "parseFloat(datum.hour) + 12"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"color": {"value": "silver"}
}
},
{
"transform": [{"filter": "datum.minute === minutes(now())"}],
"mark": {
"type": "text",
"radius": 120,
"fontWeight": 800,
"fontSize": 30,
"angle": {"expr": "datum.percentage"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"value": "————————"},
"color": {"value": "red"}
}
},
{
"transform": [
{
"filter": "datum.hour == hours(now()) || datum.hour == hours(now())-12"
},
{
"filter": "((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 1  || hours(now()) == 13) && datum.minute == '5') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 2  || hours(now()) == 14) && datum.minute == '10') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 3  || hours(now()) == 15) && datum.minute == '15') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 4  || hours(now()) == 16) && datum.minute == '20') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 5  || hours(now()) == 17) && datum.minute == '25') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 6  || hours(now()) == 18) && datum.minute == '30') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 7  || hours(now()) == 19) && datum.minute == '35') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 8  || hours(now()) == 20) && datum.minute == '40') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 9  || hours(now()) == 21) && datum.minute == '45') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 10 || hours(now()) == 22) && datum.minute == '50') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 11 || hours(now()) == 23) && datum.minute == '55') ||((minutes(now()) >= 0 && minutes(now()) <= 12) && (hours(now()) == 12 || hours(now()) == 0 ) && datum.minute == '60') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 1  || hours(now()) == 13) && datum.minute == '6') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 2  || hours(now()) == 14) && datum.minute == '11') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 3  || hours(now()) == 15) && datum.minute == '16') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 4  || hours(now()) == 16) && datum.minute == '21') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 5  || hours(now()) == 17) && datum.minute == '26') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 6  || hours(now()) == 18) && datum.minute == '31') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 7  || hours(now()) == 19) && datum.minute == '36') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 8  || hours(now()) == 20) && datum.minute == '41') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 9  || hours(now()) == 21) && datum.minute == '46') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 10 || hours(now()) == 22) && datum.minute == '51') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 11 || hours(now()) == 23) && datum.minute == '56') ||((minutes(now()) >= 13 && minutes(now()) <= 24) && (hours(now()) == 12 || hours(now()) == 0 ) && datum.minute == '1') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 1  || hours(now()) == 13) && datum.minute == '7') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 2  || hours(now()) == 14) && datum.minute == '12') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 3  || hours(now()) == 15) && datum.minute == '17') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 4  || hours(now()) == 16) && datum.minute == '22') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 5  || hours(now()) == 17) && datum.minute == '27') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 6  || hours(now()) == 18) && datum.minute == '32') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 7  || hours(now()) == 19) && datum.minute == '37') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 8  || hours(now()) == 20) && datum.minute == '42') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 9  || hours(now()) == 21) && datum.minute == '47') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 10 || hours(now()) == 22) && datum.minute == '52') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 11 || hours(now()) == 23) && datum.minute == '57') ||((minutes(now()) >= 25 && minutes(now()) <= 36) && (hours(now()) == 12 || hours(now()) == 0 ) && datum.minute == '2') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 1  || hours(now()) == 13) && datum.minute == '8') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 2  || hours(now()) == 14) && datum.minute == '13') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 3  || hours(now()) == 15) && datum.minute == '18') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 4  || hours(now()) == 16) && datum.minute == '23') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 5  || hours(now()) == 17) && datum.minute == '28') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 6  || hours(now()) == 18) && datum.minute == '33') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 7  || hours(now()) == 19) && datum.minute == '38') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 8  || hours(now()) == 20) && datum.minute == '43') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 9  || hours(now()) == 21) && datum.minute == '48') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 10 || hours(now()) == 22) && datum.minute == '53') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 11 || hours(now()) == 23) && datum.minute == '58') ||((minutes(now()) >= 37 && minutes(now()) <= 48) && (hours(now()) == 12 || hours(now()) == 0 ) && datum.minute == '3') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 1  || hours(now()) == 13) && datum.minute == '9') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 2  || hours(now()) == 14) && datum.minute == '14') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 3  || hours(now()) == 15) && datum.minute == '19') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 4  || hours(now()) == 16) && datum.minute == '24') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 5  || hours(now()) == 17) && datum.minute == '29') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 6  || hours(now()) == 18) && datum.minute == '34') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 7  || hours(now()) == 19) && datum.minute == '39') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 8  || hours(now()) == 20) && datum.minute == '44') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 9  || hours(now()) == 21) && datum.minute == '49') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 10 || hours(now()) == 22) && datum.minute == '54') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 11 || hours(now()) == 23) && datum.minute == '59') ||((minutes(now()) >= 49 && minutes(now()) <= 60) && (hours(now()) == 12 || hours(now()) == 0 ) && datum.minute == '4')"
}
],
"mark": {
"type": "text",
"radius": 80,
"fontWeight": 800,
"fontSize": 60,
"angle": {"expr": "datum.percentage"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"value": "———"},
"color": {"value": "navy"}
}
},
{
"transform": [
{
"filter": "(seconds(now()) == 0 && datum.minute == '60') ||(seconds(now()) == 1 && datum.minute == '1') ||(seconds(now()) == 2 && datum.minute == '2') ||(seconds(now()) == 3 && datum.minute == '3') ||(seconds(now()) == 4 && datum.minute == '4') ||(seconds(now()) == 5 && datum.minute == '5') ||(seconds(now()) == 6 && datum.minute == '6') ||(seconds(now()) == 7 && datum.minute == '7') ||(seconds(now()) == 8 && datum.minute == '8') ||(seconds(now()) == 9 && datum.minute == '9') ||(seconds(now()) == 10 && datum.minute == '10') ||(seconds(now()) == 11 && datum.minute == '11') ||(seconds(now()) == 12 && datum.minute == '12') ||(seconds(now()) == 13 && datum.minute == '13') ||(seconds(now()) == 14 && datum.minute == '14') ||(seconds(now()) == 15 && datum.minute == '15') ||(seconds(now()) == 16 && datum.minute == '16') ||(seconds(now()) == 17 && datum.minute == '17') ||(seconds(now()) == 18 && datum.minute == '18') ||(seconds(now()) == 19 && datum.minute == '19') ||(seconds(now()) == 20 && datum.minute == '20') ||(seconds(now()) == 21 && datum.minute == '21') ||(seconds(now()) == 22 && datum.minute == '22') ||(seconds(now()) == 23 && datum.minute == '23') ||(seconds(now()) == 24 && datum.minute == '24') ||(seconds(now()) == 25 && datum.minute == '25') ||(seconds(now()) == 26 && datum.minute == '26') ||(seconds(now()) == 27 && datum.minute == '27') ||(seconds(now()) == 28 && datum.minute == '28') ||(seconds(now()) == 29 && datum.minute == '29') ||(seconds(now()) == 30 && datum.minute == '30') ||(seconds(now()) == 31 && datum.minute == '31') ||(seconds(now()) == 32 && datum.minute == '32') ||(seconds(now()) == 33 && datum.minute == '33') ||(seconds(now()) == 34 && datum.minute == '34') ||(seconds(now()) == 35 && datum.minute == '35') ||(seconds(now()) == 36 && datum.minute == '36') ||(seconds(now()) == 37 && datum.minute == '37') ||(seconds(now()) == 38 && datum.minute == '38') ||(seconds(now()) == 39 && datum.minute == '39') ||(seconds(now()) == 40 && datum.minute == '40') ||(seconds(now()) == 41 && datum.minute == '41') ||(seconds(now()) == 42 && datum.minute == '42') ||(seconds(now()) == 43 && datum.minute == '43') ||(seconds(now()) == 44 && datum.minute == '44') ||(seconds(now()) == 45 && datum.minute == '45') ||(seconds(now()) == 46 && datum.minute == '46') ||(seconds(now()) == 47 && datum.minute == '47') ||(seconds(now()) == 48 && datum.minute == '48') ||(seconds(now()) == 49 && datum.minute == '49') ||(seconds(now()) == 50 && datum.minute == '50') ||(seconds(now()) == 51 && datum.minute == '51') ||(seconds(now()) == 52 && datum.minute == '52') ||(seconds(now()) == 53 && datum.minute == '53') ||(seconds(now()) == 54 && datum.minute == '54') ||(seconds(now()) == 55 && datum.minute == '55') ||(seconds(now()) == 56 && datum.minute == '56') ||(seconds(now()) == 57 && datum.minute == '57') ||(seconds(now()) == 58 && datum.minute == '58') ||(seconds(now()) == 59 && datum.minute == '59') ||(seconds(now()) == 60 && datum.minute == '60')"
}
],
"mark": {
"type": "text",
"radius": 135,
"fontWeight": 800,
"angle": {"expr": "datum.percentage"}
},
"encoding": {
"theta": {"field": "Cumulat", "type": "quantitative"},
"text": {"value": "———————————————————————"},
"color": {"value": "black"}
}
},
{
"transform": [
{
"filter": {
"field": "minute",
"oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 0]
}
}
],
"mark": {"type": "circle", "size": 500},
"encoding": {"color": {"value": "silver"}}
},
]
};

return spec;
}

let view;
vegaEmbed('#vis', generateSpec())
.then((result) => {
view = result.view;
})
.catch(console.error);

setInterval(() => {
const newSpec = generateSpec();
vegaEmbed('#vis', newSpec, {actions: false}).then((result) => {
view = result.view;
}).catch(console.error);
}, 1000);
</script>   
</body>
</html>
json visualization vega-lite
2个回答
0
投票

这是一个更简单的方法,也使用 svg 手。

Apple iOS 风格,带日期。

<!doctype html> 
<html> 
<head> 
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
</head>      
<body>
<div id="vis"></div>

<script type="text/javascript">
</script>

<script id="jsCode" type="text/javascript"> 

function generateSpec() {
const spec = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "Vega-lite clock",
  "usermeta": {"embedOptions": {"renderer": "svg"}},
  "data": {
    "values": [
      {"hour": "12", "min": "1", "minute": "01", "value": 1},
      {"hour": "12", "min": "2", "minute": "02", "value": 1},
      {"hour": "12", "min": "3", "minute": "03", "value": 1},
      {"hour": "12", "min": "4", "minute": "04", "value": 1},
      {"hour": "1", "min": "5", "minute": "05", "value": 1},
      {"hour": "1", "min": "6", "minute": "06", "value": 1},
      {"hour": "1", "min": "7", "minute": "07", "value": 1},
      {"hour": "1", "min": "8", "minute": "08", "value": 1},
      {"hour": "1", "min": "9", "minute": "09", "value": 1},
      {"hour": "2", "min": "10", "minute": "10", "value": 1},
      {"hour": "2", "min": "11", "minute": "11", "value": 1},
      {"hour": "2", "min": "12", "minute": "12", "value": 1},
      {"hour": "2", "min": "13", "minute": "13", "value": 1},
      {"hour": "2", "min": "14", "minute": "14", "value": 1},
      {"hour": "3", "min": "15", "minute": "15", "value": 1},
      {"hour": "3", "min": "16", "minute": "16", "value": 1},
      {"hour": "3", "min": "17", "minute": "17", "value": 1},
      {"hour": "3", "min": "18", "minute": "18", "value": 1},
      {"hour": "3", "min": "19", "minute": "19", "value": 1},
      {"hour": "4", "min": "20", "minute": "20", "value": 1},
      {"hour": "4", "min": "21", "minute": "21", "value": 1},
      {"hour": "4", "min": "22", "minute": "22", "value": 1},
      {"hour": "4", "min": "23", "minute": "23", "value": 1},
      {"hour": "4", "min": "24", "minute": "24", "value": 1},
      {"hour": "5", "min": "25", "minute": "25", "value": 1},
      {"hour": "5", "min": "26", "minute": "26", "value": 1},
      {"hour": "5", "min": "27", "minute": "27", "value": 1},
      {"hour": "5", "min": "28", "minute": "28", "value": 1},
      {"hour": "5", "min": "29", "minute": "29", "value": 1},
      {"hour": "6", "min": "30", "minute": "30", "value": 1},
      {"hour": "6", "min": "31", "minute": "31", "value": 1},
      {"hour": "6", "min": "32", "minute": "32", "value": 1},
      {"hour": "6", "min": "33", "minute": "33", "value": 1},
      {"hour": "6", "min": "34", "minute": "34", "value": 1},
      {"hour": "7", "min": "35", "minute": "35", "value": 1},
      {"hour": "7", "min": "36", "minute": "36", "value": 1},
      {"hour": "7", "min": "37", "minute": "37", "value": 1},
      {"hour": "7", "min": "38", "minute": "38", "value": 1},
      {"hour": "7", "min": "39", "minute": "39", "value": 1},
      {"hour": "8", "min": "40", "minute": "40", "value": 1},
      {"hour": "8", "min": "41", "minute": "41", "value": 1},
      {"hour": "8", "min": "42", "minute": "42", "value": 1},
      {"hour": "8", "min": "43", "minute": "43", "value": 1},
      {"hour": "8", "min": "44", "minute": "44", "value": 1},
      {"hour": "9", "min": "45", "minute": "45", "value": 1},
      {"hour": "9", "min": "46", "minute": "46", "value": 1},
      {"hour": "9", "min": "47", "minute": "47", "value": 1},
      {"hour": "9", "min": "48", "minute": "48", "value": 1},
      {"hour": "9", "min": "49", "minute": "49", "value": 1},
      {"hour": "10", "min": "50", "minute": "50", "value": 1},
      {"hour": "10", "min": "51", "minute": "51", "value": 1},
      {"hour": "10", "min": "52", "minute": "52", "value": 1},
      {"hour": "10", "min": "53", "minute": "53", "value": 1},
      {"hour": "10", "min": "54", "minute": "54", "value": 1},
      {"hour": "11", "min": "55", "minute": "55", "value": 1},
      {"hour": "11", "min": "56", "minute": "56", "value": 1},
      {"hour": "11", "min": "57", "minute": "57", "value": 1},
      {"hour": "11", "min": "58", "minute": "58", "value": 1},
      {"hour": "11", "min": "59", "minute": "59", "value": 1},
      {"hour": "12", "min": "0", "minute": "60", "value": 1}
    ]
  },
  "params": [
    {
      "name": "_svg_min",
      "value": "M -2 0 a 3 3 0 1 0 6 0 v -130 a 3 3 0 1 0 -6 0 z"
    },
    {
      "name": "_svg_hr",
      "value": "M -2 0 a 3 3 0 1 0 6 0 v -90 a 3 3 0 1 0 -6 0 z"
    },
    {"name": "_svg_second", "value": "M 0 -160 l 0 190"}
  ],
  "transform": [
    {"joinaggregate": [{"op": "sum", "field": "value", "as": "total"}]},
    {
      "sort": [{"field": "minute"}],
      "window": [{"op": "sum", "field": "value", "as": "Cumulat"}],
      "frame": [null, 0]
    },
    {
      "calculate": "(360* ((datum.Cumulat) / datum.total))-90",
      "as": "percentage"
    },
    {"calculate": "minutes(now()) / 60 * 360", "as": "min_degrees"},
    {
      "calculate": "((hours(now()) % 12) * 30) + (minutes(now()) / 60 * 30)",
      "as": "hr_degrees"
    },
    {"calculate": "seconds(now()) * 6", "as": "sec_degrees"},
    {"calculate": "timeFormat(now(), '%a %e')", "as": "curr_date1"},
    {"calculate": "timeFormat(now(), '%B')", "as": "curr_date2"}
  ],
  "layer": [
    {
      "mark": {"type": "arc", "outerRadius": 200, "innerRadius": 199},
      "encoding": {"color": {"value": "#dddddd"}}
    },
    {
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 0]
          }
        }
      ],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#1C1C1E"}
      }
    },
    {
      "transform": [{"filter": "datum.minute == minutes(now())"}],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#F79100"}
      }
    },
    {
      "transform": [{"filter": "datum.minute == seconds(now()) || seconds(now()) == 0 && datum.minute == '60'"}],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 70,
        "fontWeight": 800,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#FFFFFF"}
      }
    },
    {
      "transform": [{"filter": "datum.minute == seconds(now()) || seconds(now()) == 0 && datum.minute == '60'"}],
      "mark": {
        "type": "text",
        "radius": 190,
        "fontSize": 30,
        "fontWeight": 800,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "🢐"},
        "color": {"value": "#F79100"}
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
          }
        }
      ],
      "mark": {
        "type": "text",
        "radius": 145,
        "fontSize": 40,
        "fontWeight": 600,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "hour"},
        "color": {
          "condition": {
            "test": "datum.hour == hours(now()) || datum.hour == hours(now())-12",
            "value": "#F79100"
          },
          "value": "black"
        }
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 0]
          }
        }
      ],
      "mark": {"type": "circle", "size": 500},
      "encoding": {"color": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_min"},
        "angle": {"expr": "datum.min_degrees"}
      },
      "encoding": {"fill": {"value": "#1C1C1E"}, "stroke": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_hr"},
        "angle": {"expr": "datum.hr_degrees"}
      },
      "encoding": {"fill": {"value": "#1C1C1E"}, "stroke": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_second"},
        "angle": {"expr": "datum.sec_degrees"}
      },
      "encoding": {"fill": {"value": "#F79100"}, "stroke": {"value": "#F79100"}}
    },
    {
      "mark": {"type": "circle", "size": 200},
      "encoding": {"color": {"value": "#F79100"}}
    },
    {
      "mark": {"type": "circle", "size": 50},
      "encoding": {"color": {"value": "#FFF"}}
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [14]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 18,
        "fontWeight": 600,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "curr_date1"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [16]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 16,
        "fontWeight": 400,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "curr_date2"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [60]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 28,
        "fontWeight": 400,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "VL"},
        "color": {"value": "#F79100"}
      }
    }
  ]
};

return spec;
}

let view;
vegaEmbed('#vis', generateSpec())
.then((result) => {
view = result.view;
})
.catch(console.error);

setInterval(() => {
const newSpec = generateSpec();
vegaEmbed('#vis', newSpec, {renderer: "svg", actions: false}).then((result) => {
view = result.view;
}).catch(console.error);
}, 1000);
</script>   
</body>
</html>

亚当


0
投票

这里有一种在 Vega-Lite 中获取计时器的方法,这样你就不需要嵌入 vega。您将在编辑器中看到一条下划线,但您可以忽略它。

{
  "name": "time", 
     "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}] 
},

每秒更新:

VL中工作时钟的完整代码。

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "Vega-lite clock",
  "usermeta": {"embedOptions": {"renderer": "svg"}},
  "data": {
    "values": [
      {"hour": "12", "min": "1", "minute": "01", "value": 1},
      {"hour": "12", "min": "2", "minute": "02", "value": 1},
      {"hour": "12", "min": "3", "minute": "03", "value": 1},
      {"hour": "12", "min": "4", "minute": "04", "value": 1},
      {"hour": "1", "min": "5", "minute": "05", "value": 1},
      {"hour": "1", "min": "6", "minute": "06", "value": 1},
      {"hour": "1", "min": "7", "minute": "07", "value": 1},
      {"hour": "1", "min": "8", "minute": "08", "value": 1},
      {"hour": "1", "min": "9", "minute": "09", "value": 1},
      {"hour": "2", "min": "10", "minute": "10", "value": 1},
      {"hour": "2", "min": "11", "minute": "11", "value": 1},
      {"hour": "2", "min": "12", "minute": "12", "value": 1},
      {"hour": "2", "min": "13", "minute": "13", "value": 1},
      {"hour": "2", "min": "14", "minute": "14", "value": 1},
      {"hour": "3", "min": "15", "minute": "15", "value": 1},
      {"hour": "3", "min": "16", "minute": "16", "value": 1},
      {"hour": "3", "min": "17", "minute": "17", "value": 1},
      {"hour": "3", "min": "18", "minute": "18", "value": 1},
      {"hour": "3", "min": "19", "minute": "19", "value": 1},
      {"hour": "4", "min": "20", "minute": "20", "value": 1},
      {"hour": "4", "min": "21", "minute": "21", "value": 1},
      {"hour": "4", "min": "22", "minute": "22", "value": 1},
      {"hour": "4", "min": "23", "minute": "23", "value": 1},
      {"hour": "4", "min": "24", "minute": "24", "value": 1},
      {"hour": "5", "min": "25", "minute": "25", "value": 1},
      {"hour": "5", "min": "26", "minute": "26", "value": 1},
      {"hour": "5", "min": "27", "minute": "27", "value": 1},
      {"hour": "5", "min": "28", "minute": "28", "value": 1},
      {"hour": "5", "min": "29", "minute": "29", "value": 1},
      {"hour": "6", "min": "30", "minute": "30", "value": 1},
      {"hour": "6", "min": "31", "minute": "31", "value": 1},
      {"hour": "6", "min": "32", "minute": "32", "value": 1},
      {"hour": "6", "min": "33", "minute": "33", "value": 1},
      {"hour": "6", "min": "34", "minute": "34", "value": 1},
      {"hour": "7", "min": "35", "minute": "35", "value": 1},
      {"hour": "7", "min": "36", "minute": "36", "value": 1},
      {"hour": "7", "min": "37", "minute": "37", "value": 1},
      {"hour": "7", "min": "38", "minute": "38", "value": 1},
      {"hour": "7", "min": "39", "minute": "39", "value": 1},
      {"hour": "8", "min": "40", "minute": "40", "value": 1},
      {"hour": "8", "min": "41", "minute": "41", "value": 1},
      {"hour": "8", "min": "42", "minute": "42", "value": 1},
      {"hour": "8", "min": "43", "minute": "43", "value": 1},
      {"hour": "8", "min": "44", "minute": "44", "value": 1},
      {"hour": "9", "min": "45", "minute": "45", "value": 1},
      {"hour": "9", "min": "46", "minute": "46", "value": 1},
      {"hour": "9", "min": "47", "minute": "47", "value": 1},
      {"hour": "9", "min": "48", "minute": "48", "value": 1},
      {"hour": "9", "min": "49", "minute": "49", "value": 1},
      {"hour": "10", "min": "50", "minute": "50", "value": 1},
      {"hour": "10", "min": "51", "minute": "51", "value": 1},
      {"hour": "10", "min": "52", "minute": "52", "value": 1},
      {"hour": "10", "min": "53", "minute": "53", "value": 1},
      {"hour": "10", "min": "54", "minute": "54", "value": 1},
      {"hour": "11", "min": "55", "minute": "55", "value": 1},
      {"hour": "11", "min": "56", "minute": "56", "value": 1},
      {"hour": "11", "min": "57", "minute": "57", "value": 1},
      {"hour": "11", "min": "58", "minute": "58", "value": 1},
      {"hour": "11", "min": "59", "minute": "59", "value": 1},
      {"hour": "12", "min": "0", "minute": "60", "value": 1}
    ]
  },
  "params": [
    {
      "name": "_svg_min",
      "value": "M -2 0 a 3 3 0 1 0 6 0 v -130 a 3 3 0 1 0 -6 0 z"
    },
    {
      "name": "_svg_hr",
      "value": "M -2 0 a 3 3 0 1 0 6 0 v -90 a 3 3 0 1 0 -6 0 z"
    },
    {"name": "_svg_second", "value": "M 0 -160 l 0 190"},
    {
      "name": "time",
      "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
    }
  ],
  "transform": [
    {"joinaggregate": [{"op": "sum", "field": "value", "as": "total"}]},
    {
      "sort": [{"field": "minute"}],
      "window": [{"op": "sum", "field": "value", "as": "Cumulat"}],
      "frame": [null, 0]
    },
    {
      "calculate": "(360* ((datum.Cumulat) / datum.total))-90",
      "as": "percentage"
    },
    {"calculate": "minutes(time) / 60 * 360", "as": "min_degrees"},
    {
      "calculate": "((hours(time) % 12) * 30) + (minutes(time) / 60 * 30)",
      "as": "hr_degrees"
    },
    {"calculate": "seconds(time) * 6", "as": "sec_degrees"},
    {"calculate": "timeFormat(time, '%a %e')", "as": "curr_date1"},
    {"calculate": "timeFormat(time, '%B')", "as": "curr_date2"}
  ],
  "layer": [
    {
      "mark": {"type": "arc", "outerRadius": 200, "innerRadius": 199},
      "encoding": {"color": {"value": "#dddddd"}}
    },
    {
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 0]
          }
        }
      ],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#1C1C1E"}
      }
    },
    {
      "transform": [{"filter": "datum.minute == minutes(time)"}],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 50,
        "fontWeight": 400,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#F79100"}
      }
    },
    {
      "transform": [
        {
          "filter": "datum.minute == seconds(time) || seconds(time) == 0 && datum.minute == '60'"
        }
      ],
      "mark": {
        "type": "text",
        "radius": 180,
        "fontSize": 70,
        "fontWeight": 800,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "-"},
        "color": {"value": "#FFFFFF"}
      }
    },
    {
      "transform": [
        {
          "filter": "datum.minute == seconds(time) || seconds(time) == 0 && datum.minute == '60'"
        }
      ],
      "mark": {
        "type": "text",
        "radius": 190,
        "fontSize": 30,
        "fontWeight": 800,
        "angle": {"expr": "datum.percentage"}
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "🢐"},
        "color": {"value": "#F79100"}
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
          }
        }
      ],
      "mark": {
        "type": "text",
        "radius": 145,
        "fontSize": 40,
        "fontWeight": 600,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "hour"},
        "color": {
          "condition": {
            "test": "datum.hour == hours(time) || datum.hour == hours(time)-12",
            "value": "#F79100"
          },
          "value": "black"
        }
      }
    },
    {
      "transform": [
        {
          "filter": {
            "field": "minute",
            "oneOf": [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 0]
          }
        }
      ],
      "mark": {"type": "circle", "size": 500},
      "encoding": {"color": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_min"},
        "angle": {"expr": "datum.min_degrees"}
      },
      "encoding": {"fill": {"value": "#1C1C1E"}, "stroke": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_hr"},
        "angle": {"expr": "datum.hr_degrees"}
      },
      "encoding": {"fill": {"value": "#1C1C1E"}, "stroke": {"value": "#1C1C1E"}}
    },
    {
      "mark": {
        "type": "point",
        "size": 5.1,
        "shape": {"expr": "_svg_second"},
        "angle": {"expr": "datum.sec_degrees"}
      },
      "encoding": {"fill": {"value": "#F79100"}, "stroke": {"value": "#F79100"}}
    },
    {
      "mark": {"type": "circle", "size": 200},
      "encoding": {"color": {"value": "#F79100"}}
    },
    {
      "mark": {"type": "circle", "size": 50},
      "encoding": {"color": {"value": "#FFF"}}
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [14]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 18,
        "fontWeight": 600,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "curr_date1"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [16]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 16,
        "fontWeight": 400,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"field": "curr_date2"},
        "color": {"value": "silver"}
      }
    },
    {
      "transform": [{"filter": {"field": "minute", "oneOf": [60]}}],
      "mark": {
        "type": "text",
        "radius": 80,
        "fontSize": 28,
        "fontWeight": 400,
        "font": "Arial"
      },
      "encoding": {
        "theta": {"field": "Cumulat", "type": "quantitative"},
        "text": {"value": "VL"},
        "color": {"value": "#F79100"}
      }
    }
  ]
}
© www.soinside.com 2019 - 2024. All rights reserved.