Public
Edited
Jan 16, 2023
1 star
Insert cell
Insert cell
main = {
let dom = html`<div style="position: relative; height:100%">
<div class='dim-select'
style='position:absolute;
z-index:2;
right: 10% ;
background: #fff;
box-shadow: 4px 7px 8px #eee;
border: 1px solid #eee;' >
${selectInput}
${isShowSelect ? search : ""}
${isShowSelect ? dimList : []}
</div>
<div class='dims-chart' style="height: 100% ;min-height:400px; width:100%"></div>
</div>`;
setTimeout(() => {
const k = getUserStorageKey();
const val = sessionStorage.getItem(k);
if (val && chooseDims[0] !== val) {
mutable chooseDims = [val];
}
}, 100);
return dom;
}
Insert cell
mutable searchWord = ""
Insert cell
mutable chooseDims = _.take(legend, 1)
Insert cell
mutable isShowSelect = false
Insert cell
findParentBySelector = {
function collectionHas(a, b) {
//helper function (see below)
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] == b) return true;
}
return false;
}
return function findParentBySelector(elm, selector) {
var all = document.querySelectorAll(selector);
var cur = elm.parentNode;
while (cur && !collectionHas(all, cur)) {
//keep going up until you find a match
cur = cur.parentNode; //go up
}
return cur; //will return null if not found
}
}
Insert cell
legend = _.keys(_.groupBy(finalDat, "mergedDim")).filter((l) =>
_.includes(l, searchWord)
)
Insert cell
getNoChooseDims = () => _.filter(legend, (d) => !_.includes(chooseDims, d))
Insert cell
Insert cell
selectInput = {
let input = html`<input style='height: 20px ;
line-height: 40px;
width:400px;
text-align: center;'
placeholder='维度选择:${
_.isEmpty(chooseDims) ? "未选择" : chooseDims
}' />`;
//筛选结果栏 输入框获取焦点事件
input.onclick = () => {
mutable isShowSelect = !isShowSelect;
};
return input;
}
Insert cell
// 维度栏
dimList = {
let ls = html`<ul class='dims-list' style='list-style: none; padding: 0; height: 200px;max-width:400px; overflow: auto; border-bottom: 1px solid #eee; margin: 0;'>
${_.map(legend, (len) => {
const color = !_.includes(chooseDims, len) ? "#fff" : "#e6f7ff";
return `<li style='cursor: pointer;background: ${color}; margin:5px 0; padding: 0 5px;'>${len} </li>`;
})}
</ul>`;
ls.onclick = (e) => {
const val = e.target.innerText;
mutable isShowSelect = false;
mutable chooseDims = [val];
sessionStorage.setItem(getUserStorageKey(), val);
};
return ls;
}
Insert cell
hashCode = function (str) {
var hash = 0,
i,
chr;
if (str.length === 0) return hash;
for (i = 0; i < str.length; i++) {
chr = str.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
Insert cell
function getUserStorageKey() {
const userId = _.get(window.sugo, "user.id", "unknown-user");
const hash = hashCode(
`${userId}:${slice.params.metrics}:${slice.params.tabKey}`
);
return `sliceTmpSetting:${hash}`;
}
Insert cell
groupedData = {
return _.groupBy(
_.filter(finalDat, (d) => _.includes(chooseDims, d.mergedDim)),
"mergedDim"
);
}
Insert cell
// 2021.12.10 二维折线图1(标注最大值最小值)
// 单指标;2个维度(时间维度 + 其他维度合并一维);源数据保留2位小数;
Insert cell
dimensions = ["time", "TLJ", "province", "city"]
Insert cell
finalDim = [_.first(dimensions), "mergedDim"]
Insert cell
metrics = ['count']
Insert cell
Insert cell
finalDat = {
let restDims = _.drop(dimensions, 1);
const data2 = await queryData(data);
return _.map(data2, (d) => {
return {
...d,
mergedDim: `${restDims.map((dim) => _.trim(d[dim])).join("-")}`
};
});
}
Insert cell
async function queryData(data0) {
// 时间:默认取值最近 n 天,至昨天; n 根据 timeRange 计算
const timeDim =
_.find(["YEAR", "MONTH", "DAY"], (dimName) => _.get(data0, [0, dimName])) ||
"MONTH";
let latestData = await modifyParamsAndQuery((slice) => {
const timeRange = _.get(slice, "params.extraData.timeRange") || [];
const dt = moment().add(-1, timeDim).diff(timeRange[1], timeDim);

return copyOnUpdate(slice, "params.extraData.timeRange", (arr) =>
_.map(arr, (t, ti) => {
// dt = 昨天 - until
// next = timeRange + dt
return moment(t, "YYYY-MM-DD").add(dt, timeDim).format("YYYY-MM-DD");
})
);
});
return _.get(latestData, "resultSet") || [];
}
Insert cell
slice = ({id: 0})
Insert cell
copyOnUpdate = _.identity
Insert cell
moment = window.moment || require("moment")
Insert cell
modifyParamsAndQuery = async (mapper) => {
return {
_tempMetric_xx: 0,
resultSet: data
};
}
Insert cell
translationDict = ({})
Insert cell
Insert cell
metricFormatterFn = metricsFormatDict[metrics[0]] || _.identity
Insert cell
Insert cell
option = {
let [timeDim, mergedDim] = finalDim;
let [metric] = metrics;
return {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow"
},
formatter: echartsLikeTooltipFormatter
},
// legend: {
// type: 'scroll'
// },
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true
},
xAxis: {
type: "category",
data: _.uniq((finalDat || []).map((d) => d[timeDim])),
//data: (data || []).map((d) => dimensions.map(dim => _.trim(d[dim])).join('-')),
//axisLabel: { rotate: 30 },
axisTick: { alignWithLabel: true },
axisLine: { onZero: false }
},
yAxis: {
type: "value",
boundaryGap: [0, 0.01],
scale: true //非0
},
color: [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
series: [
..._.map(groupedData, (arr, group) => {
return {
name: group,
type: "line",
symbol: "emptyCircle",
data: arr.map((d) => _.round(d[metric], 2)),
areaStyle: { normal: {} },
smooth: true,
markLine: {
silent: true,
lineStyle: {
color: "#FBDB10",
type: "solid"
},
label: {
position: "insideStartTop",
color: "#FBDB10",
formatter: "均值:{c}",
textShadowColor: "#fff",
textShadowBlur: 0.5,
textShadowOffsetX: 0.5,
textShadowOffsetY: 0.5,
fontSize: 14
},
data: [
{
yAxis: _.round(_.meanBy(arr, metric), 2)
}
]
},
markPoint: {
data: [
{ type: "max", name: "Max" },
{ type: "min", name: "Min" }
],
label: {
formatter: (params) => {
return metricFormatterFn(params.value);
}
}
}
};
})
]
};
}
Insert cell
chartInst = echarts.init(main.querySelector('.dims-chart'))
Insert cell
chartInst.setOption(option, { notMerge: true, lazyUpdate: true })
Insert cell
(width, chartInst.resize()) // 自适应宽度
Insert cell
echarts = window.echarts || require("https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js")
Insert cell
_ = window._ || require("lodash")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more