{"id":24673,"date":"2024-03-14T17:02:30","date_gmt":"2024-03-14T17:02:30","guid":{"rendered":"https:\/\/www.highcharts.com\/blog\/?p=24673"},"modified":"2026-01-13T11:45:31","modified_gmt":"2026-01-13T11:45:31","slug":"drawing-with-data-part-1","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/tutorials\/drawing-with-data-part-1\/","title":{"rendered":"Drawing With Data: Part 1"},"content":{"rendered":"<p>Drawing with data seems like an exercise in overkill, especially in the age of AI-powered image creation and editing. It\u2019s a manual process that involves a lot of trial and error, and the end result is the same as something you could do in minutes using a basic drawing tool. So why do it? Because it\u2019s a fun and challenging way to learn the ins and outs of some of Highcharts\u2019 coolest features.<\/p>\n<h2>Inspiration<\/h2>\n<p>A few years ago, I worked on a chart animation that included a network graph. I always liked the way the simulated forces of the graph\u2019s layout algorithm caused its nodes and links to undulate, like a graceful jellyfish-octopus hybrid. So I decided to resurrect this shy creature and create an underwater world for it using some of my favorite Highcharts series types and features.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-24757\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154010\/original-network.gif\" alt=\"An animated network graph chart whose movement resembles an underwater sea creature\" width=\"1096\" height=\"412\" \/><\/p>\n<p>For inspiration, I grabbed a screenshot from an episode of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Jungle_Beat_(TV_series)\" target=\"_blank\" rel=\"noopener\">Jungle Beat<\/a>, an animated series about different animals and their adventures. This particular episode happens to be about an \u201c<a href=\"https:\/\/youtu.be\/u8dhw8acGMY?t=19\" target=\"_blank\" rel=\"noopener\">outstanding octopus<\/a>.\u201d<\/p>\n<p>The shapes of the underwater foliage, sand and sunbeams are pretty basic, and I like the use of atmospheric perspective, where stuff in the background appears fuzzy and darker than the stuff in the foreground.<\/p>\n<p>I then created a less-detailed sketch of the screenshot (on the right below) to make it easier to draw. This image will serve as a traceable template for my underwater chart art scene.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-24758\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154354\/both-seas.jpg\" alt=\"side-by-side images: screen shot of a cartoon underwater scene on the left, simplified illustration on the right\" width=\"1160\" height=\"322\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154354\/both-seas.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154354\/both-seas-560x155.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154354\/both-seas-760x211.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2024\/03\/14154354\/both-seas-768x213.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Setting Up The Chart<\/h2>\n<p>To prep for drawing, I set up a basic chart configuration, disabled the <code>credits<\/code> and <code>legend<\/code> and set the <code>title<\/code> text to null. I also set the chart margins to 0 so my scene will extend to the edges of my chart container.<\/p>\n<p>I then add an <code>xAxis<\/code> and\u00a0 <code>yAxis<\/code>,\u00a0each with a min of 0 and a max of 20. Establishing these min\/max ranges provides a predictable scale that helps me position my drawing\u2019s data points.<\/p>\n<p>Finally, I set the <code>plotBackgroundImage<\/code> to the sketch I made based on the Jungle Beat screenshot.<\/p>\n<pre>const chart = Highcharts.chart('container', {\r\n\tchart: {\r\n    \t    plotBackgroundImage: 'sea.png',\r\n    \t    margin: 0\r\n\t},\r\n\tlegend: {\r\n    \t    enabled: false\r\n\t},\r\n\tcredits: {\r\n    \t    enabled: false\r\n\t},\r\n\ttitle: {\r\n    \t    text: null\r\n\t},\r\n\txAxis: [\r\n    \t{\r\n        \tmin: 0,\r\n        \tmax: 20,\r\n        \tvisible: false\r\n    \t}\r\n\t],\r\n\tyAxis: [\r\n    \t{\r\n        \tmin: 0,\r\n        \tmax: 20,\r\n        \tvisible: false\r\n    \t}\r\n\t],\r\n\tseries: [ ]\r\n});\r\n<\/pre>\n<p>One final tip: I recommend assigning a fixed height and width to the chart container div. This ensures the positions of the points will be consistent, making it easier to draw.<\/p>\n<p>Here\u2019s my setup:<\/p>\n<p class=\"demo-container\"><iframe style=\"width: 100%;\" title=\"A basic chart configuration with a plot background image\" src=\"https:\/\/codepen.io\/nasin\/embed\/WNWNzNB?default-tab=result&amp;theme-id=light\" height=\"700\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/nasin\/pen\/WNWNzNB\"> Jellypus 1<\/a> by Nancy Dillon (<a href=\"https:\/\/codepen.io\/nasin\">@nasin<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<h2>The Best Series for the Scene<\/h2>\n<p>With my basic chart configuration in place, I\u2019m almost ready to start drawing. But what\u2019s the best series to use to recreate the smooth curves of my underwater scene? I\u2019m thinking <code>areasplinerange.<\/code><\/p>\n<p>In any range series, each data point has three values: an x-axis value and two y values that denote the high and low points of a range.<\/p>\n<p>When connected, these points form a shaded area that visualizes the span between the high and low values, illustrating the data\u2019s variability over time and helping to identify trends and statistical outliers.<\/p>\n<p class=\"demo-container\"><iframe loading=\"lazy\" style=\"border: none;\" title=\"Area spline range series that shows daily temperature variation over the course of one year\" src=\"https:\/\/www.highcharts.com\/samples\/embed\/stock\/demo\/areasplinerange\" width=\"100%\" height=\"480px\"><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><\/iframe><\/p>\n<p>In an area spline range series, the points connect through a spline curve, where the curve&#8217;s shape is influenced by the high and low ranges of individual points, as well as the difference between consecutive points. These smooth curves are ideal for creating the soft shapes of my underwater scene.<\/p>\n<h2>Drop Some Points<\/h2>\n<p>To get started, I create an <code>areasplinerange<\/code> series and populate it with three data points that somewhat correspond to the left-most shape in my sketch.<\/p>\n<pre> {\r\n     type: 'areasplinerange',\r\n     data: [{\r\n             x: 0.5,\r\n             low: 2,\r\n             high: 15\r\n         },\r\n         {\r\n             x: 1,\r\n             low: 3,\r\n             high: 18\r\n         },\r\n         {\r\n             x: 2,\r\n             low: 4,\r\n             high: 20\r\n         }\r\n     ]\r\n }\r\n<\/pre>\n<p class=\"demo-container\"><iframe style=\"width: 100%;\" title=\"A basic chart configuration with a plot background image\" src=\"https:\/\/codepen.io\/nasin\/embed\/jOROorp?default-tab=result&amp;theme-id=light\" height=\"700\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/nasin\/pen\/jOROorp\"><br \/>\nJellypus 2<\/a> by Nancy Dillon (<a href=\"https:\/\/codepen.io\/nasin\">@nasin<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<p>The results are pretty good but not there yet. Using trial and error to manually position each point will take a while, so I\u2019m going to use Highcharts\u2019 dragDrop feature to quickly position my points.<\/p>\n<p>To enable drag and drop functionality in my chart, I\u2019ll add the draggable points JavaScript module to my HTML file.<\/p>\n<pre>&lt;script src=\"https:\/\/code.highcharts.com\/modules\/draggable-points.js\"&gt;&lt;\/script&amp;gt<\/pre>\n<p>Then, I\u2019ll add the <code>plotOptions<\/code> object to my chart configuration and create a <code>series<\/code> entry for which I\u2019ll enable <code>dragDrop<\/code> and set <code>draggableY<\/code> and <code>draggableX<\/code> to true.<\/p>\n<pre>plotOptions: {\r\n    series: {\r\n        dragDrop: {\r\n            draggableX: true,\r\n            draggableY: true\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Now, I can easily drag the points where they need to be. I just need an easy way to see the modified point data.<\/p>\n<h2>Fixed-Position Tooltips<\/h2>\n<p>To make it easy to gather the new x and y values of my dragged points, I\u2019ll set my <code>tooltip<\/code> to a fixed position.<\/p>\n<p>To position my tooltip, I\u2019ll use the <code>tooltip.positioner<\/code> function to return fixed x and y coordinates.<\/p>\n<pre>tooltip: {\r\n    positioner: function() {\r\n        return {\r\n            x: 20,\r\n            y: 20\r\n        };\r\n    },\r\n}<\/pre>\n<h2>Let\u2019s Drawg<\/h2>\n<p>With my first underwater tree traced,\u00a0 I\u00a0 add as many <code>areasplinerange<\/code> series as I need for the other trees and use the \u201cdrawg\u201d method to drag the points into place and adjust their x and y values based on the info gathered from the fixed-position tooltip.<\/p>\n<p>To make sure I\u2019ve traced everything, I remove my <code>plotBackgroundImage<\/code>. Here\u2019s my drawing so far.<\/p>\n<p class=\"demo-container\"><iframe style=\"width: 100%;\" title=\"Result of tracing a drawing using area spline ranges\" src=\"https:\/\/codepen.io\/nasin\/embed\/wvZvbmX?default-tab=result&amp;theme-id=light\" height=\"710\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/nasin\/pen\/wvZvbmX\"><br \/>\nJellypus 4<\/a> by Nancy Dillon (<a href=\"https:\/\/codepen.io\/nasin\">@nasin<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<h2>Some helpful tips<\/h2>\n<p>Here are some helpful tips for making the \u201cdrawg\u201d\u00a0 process as frustration free as possible.<\/p>\n<h3>Work with one series at a time.<\/h3>\n<p>Point dragging becomes confusing when dealing with multiple series.<\/p>\n<p>To alleviate distractions, I set each series\u2019\u00a0<code>enableMouseTracking<\/code> property to false once I\u2019m done dragging its points into place.\u00a0 This disables all events triggered by mouse interactions (like point hover effects and tooltip display), making it easier to concentrate on the series I\u2019m working with.<\/p>\n<h3>Sometimes, the tooltip gets in the way<\/h3>\n<p>Even though it&#8217;s in a fixed position, the tooltip sometimes obscures my view. To fix this, I assign my chart configuration to a global variable called \u201cchart\u201d that I can invoke in my browser console. This way, I can easily turn the tooltip on and off without having to constantly change my chart configuration code.<\/p>\n<pre>chart.update({tooltip:{enabled: false}})<\/pre>\n<h2>Conclusion<\/h2>\n<p>In this article, we drew some weird shapes with several <code>areasplinerange<\/code> series and made good use of Highcharts&#8217; draggable points module and fixed-position tooltips and learned how to disable mouse events.<\/p>\n<p>In the next tutorial, I will introduce you to Highcharts\u2019 <code>styledMode<\/code>, a cool feature that deactivates configuration styling options so you can control the look and feel of your chart with just CSS. We will use it to transform our amorphous area spline range series into underwater trees and add some atmospheric effects.<\/p>\n<h2><strong>Related posts<\/strong><\/h2>\n<ul>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/us-map-of-top-100-cities-using-highcharts\/\">US map of top 100 cities using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/visualizing-geospatial-data-with-highcharts-maps\/\">Visualizing geospatial data with Highcharts Maps<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/maps-with-latitude-longitude-using-highcharts\/\">Maps with latitude longitude using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/choropleth-map-examples-using-highcharts\/\">Choropleth map examples using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/lightning-map-create-your-own-using-highcharts\/\">Lightning map: create your own using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/inspirations\/javascript-maps-with-highcharts\/\">JavaScript maps with Highcharts<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Follow along as we draw an underwater forest using data.<\/p>\n","protected":false},"author":250,"featured_media":24708,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"meta_title":"","meta_description":"","hc_selected_options":[],"footnotes":""},"categories":[210],"tags":[1063,1094],"coauthors":[786],"class_list":["post-24673","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-data-visualization","tag-highcharts-core"],"_links":{"self":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/users\/250"}],"replies":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/comments?post=24673"}],"version-history":[{"count":3,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24673\/revisions"}],"predecessor-version":[{"id":26033,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24673\/revisions\/26033"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/24708"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=24673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=24673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=24673"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=24673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}