<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>FlowRenderer with visual variables | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
<body class="calcite-mode-dark">
<arcgis-map center="-98, 39" zoom="4">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-expand slot="top-left">
<arcgis-legend></arcgis-legend>
<arcgis-expand slot="top-right" expand-icon="sliders-horizontal">
<calcite-card id="controls" class="calcite-mode-dark">
<div slot="heading">Controls</div>
label-handles></calcite-slider>
label-handles></calcite-slider>
label-handles></calcite-slider>
label-handles></calcite-slider>
label-handles></calcite-slider>
<calcite-segmented-control id="flowRepresentation">
<calcite-segmented-control-item value="flow-to">To</calcite-segmented-control-item>
<calcite-segmented-control-item value="flow-from" checked
>From</calcite-segmented-control-item
</calcite-segmented-control>
<calcite-segmented-control id="trailCap">
<calcite-segmented-control-item value="butt" checked
>Butt</calcite-segmented-control-item
<calcite-segmented-control-item value="round">Round</calcite-segmented-control-item>
</calcite-segmented-control>
<small>*Round caps are only supported when trail width is greater than 3pt</small>
<calcite-checkbox id="effectsEnabled" checked></calcite-checkbox>
const [Map, ImageryTileLayer] = await $arcgis.import([
"@arcgis/core/layers/ImageryTileLayer.js",
const viewElement = document.querySelector("arcgis-map");
const layer = new ImageryTileLayer({
url: "https://tiledimageservices.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/NLDAS_Hourly_8_30_2021/ImageServer",
type: "flow", // autocasts to new FlowRenderer
// color: [50, 120, 240, 1],
color: [40, 146, 199, 1],
color: [160, 194, 155, 1],
color: [218, 230, 119, 1],
effect: "bloom(1.5, 0.5px, 0)",
basemap: "dark-gray-vector",
const sliderProps = ["trailWidth", "density", "maxPathLength", "flowSpeed", "trailLength"];
sliderProps.forEach((prop) => {
document.getElementById(prop).addEventListener("calciteSliderChange", updateRenderer);
.getElementById("flowRepresentation")
.addEventListener("calciteSegmentedControlChange", updateRenderer);
.getElementById("trailCap")
.addEventListener("calciteSegmentedControlChange", updateRenderer);
.getElementById("effectsEnabled")
.addEventListener("calciteCheckboxChange", updateEffect);
function updateEffect(event) {
let checkbox = event.target.checked ? "bloom(1.5, 0.5px, 0)" : null;
function updateRenderer(event) {
let propName = event.target.id;
let propValue = event.target.value;
if (propName && propValue != null) {
let tempRenderer = layer.renderer.clone();
tempRenderer[propName] = propValue;
layer.renderer = tempRenderer;