Composition of layer

Use layer composition to superpose multiple layers to achieve compound plots, annotations and what not

main
run-button
run-button
reset-button
        let env = muze();
        const DataModel = muze.DataModel;
        const share = muze.Operators.share;
        const DateTimeFormatter = muze.utils.DateTimeFormatter;
	
    	const rootData = new DataModel(data, schema);

        env = env.data(rootData).minUnitHeight(40).minUnitWidth(40);
        const rows = [[], [share('minDays', 'days at or above 32 deg', 'maxDays')]];
        env.canvas()
            .rows(rows)
            .columns(['time'])
            .width(1000)
            .height(500)
            .color({
                value: '#f07520'
            })
            .config({
                gridLines: {
                    x: {
                        show: true
                    }
                },
                axes: {
                    y: {
                        domain: [180, 320],
                        name: 'Average number of days at or above 32˚C',
                        numberOfTicks: 5
                    }
                },
                interaction: {
                    tooltip: {
                        formatter: (dm) => {
                            const dataArr = dm.getData().data;
                            const fieldsConfig = dm.getFieldsConfig();
                            const maxDayIndex = fieldsConfig.maxDays.index;
                            const minDayIndex = fieldsConfig.minDays.index;
                            return [
                                ['Year: ', {
                                    value: DateTimeFormatter.formatAs(dataArr[0][fieldsConfig.time.index], '%Y'),
                                    className: 'muze-tooltip-value'
                                }],
                                ['Days at or above 32 deg: ', {
                                    value: Math.floor(dataArr[0][fieldsConfig['days at or above 32 deg'].index]),
                                    className: 'muze-tooltip-value'
                                }],
                                ['Range: ', {
                                    value: `${Math.floor(dataArr[0][minDayIndex])} - ${Math.floor(dataArr[0][maxDayIndex])}`,
                                    className: 'muze-tooltip-value'
                                }]
                            ];
                        }
                    }
                }
            })
            .layers([{
                mark: 'line',
                className: 'line-plot-item',
                encoding: {
                    y: 'days at or above 32 deg'
                },
                interpolate: 'catmullRom'
            }, {
                mark: 'area',
                className: 'area-layer',
                encoding: {
                    y: 'minDays',
                    y0: 'maxDays',
                    color: {
                        value: () => '#fdb92b'
                    }
                },
                transition: {
                    duration: 0
                },
                interpolate: 'catmullRom'
            }, {
                mark: 'text',
                className: 'text-layer',
                encoding: {
                    y: 'days at or above 32 deg',
                    text: {
                        field: 'time',
                        formatter: val => DateTimeFormatter.formatAs(val, '%Y')
                    },
                    color: {
                        value: () => '#000'
                    }
                },
                source: dt => dt.select(fields =>
                    [1992, 2018, 2072].indexOf(new Date(fields.time.value).getFullYear()) !== -1),
                encodingTransform: (points) => {
                    for (let i = 0, len = points.length; i < len; i++) {
                        points[i].update.y -= 10;
                        if (i === 0) {
                            points[i].text += '  Born';
                            points[i].update.x -= 30;
                        }
                        if (i === len - 1) {
                            points[i].text += ' Age 80';
                            points[i].update.x -= 30;
                        }
                    }
                    return points;
                }
            }, {
                mark: 'point',
                className: 'anchor-indicator',
                encoding: {
                    y: 'days at or above 32 deg',
                    size: {
                        value: 100
                    },
                    color: {
                        value: () => '#ff0000'
                    }
                },
                source: dt => dt.select(fields =>
                    [1992, 2018, 2072].indexOf(new Date(fields.time.value).getFullYear()) !== -1)
            }, {
                mark: 'tick',
                className: 'tick-layer',
                encoding: {
                    y: 'maxDays',
                    y0: 'minDays'
                },
                source: dt => dt.select(fields =>
                    [1992, 2018, 2072].indexOf(new Date(fields.time.value).getFullYear()) !== -1)
            }])
            .title('Days at or above 32°C per year', {
                align: 'center'
            })
            .subtitle('A Range Area Plot', {
                align: 'center'
            })
            .mount('#chart-container');