{"rowid": 23, "title": "Animating Vectors with SVG", "contents": "It is almost 2014 and fifteen years ago the W3C started to develop a web-based scalable vector graphics (SVG) format. As web technologies go, this one is pretty old and well entrenched. \n\nSee the Pen yJflC by Drew McLellan (@drewm) on CodePen\n\n\nEmbed not working on your device? Try direct. \n\nUnlike rasterized images, SVG files will stay crisp and sharp at any resolution. With high-DPI phones, tablets and monitors, all those rasterized icons are starting to look a bit old and blocky. There are several options to get simpler, decorative pieces to render smoothly and respond to various device widths, shapes and sizes. Symbol fonts are one option; the other is SVG.\n\nI\u2019m a big fan of SVG. SVG is an XML format, which means it is possible to write by hand or to script. The most common way to create an SVG file is through the use of various drawing applications like Illustrator, Inkscape or Sketch. All of them open and save the SVG format.\n\nBut, if SVG is so great, why doesn\u2019t it get more attention?\n\nThe simple answer is that for a long time it wasn\u2019t well supported, so no one touched the technology. SVG\u2019s adoption has always been hampered by browser support, but that\u2019s not the case any more. Every modern browser (at least three versions back) supports SVG. Even IE9. \n\nAlthough the browsers support SVG, it is implemented in many different ways.\n\nSVG in HTML\n\nSome browsers allow you to embed SVG right in the HTML: the element. Treating SVG as a first-class citizen works \u2014 sometimes. Another way to embed SVG is via the element; using the src attribute, you can refer to an SVG file. Again, this only works sometimes and leaves you in a tight space if you need to have a fallback for older browsers. The most common solution is to use the element, with the data attribute referencing the SVG file. When a browser does not support this, it falls back to the content inside the . This could be a rasterized fallback . This method gets you the best of both worlds: a nice vector image with an alternative rasterized image for browsers that don\u2019t support SVG. The downside is that you need to manage both formats, and some browsers will download both the SVG and the rasterized version, becoming a performance problem.\n\nAlexey Ten came up with a brilliant little trick that uses inline SVG combined with an SVG element. This has an SVG href pointing to the vector SVG representation and a src attribute to the rasterized version. Older browsers will rewrite the element as and use the rasterized src attribute, but modern browsers will show the vector SVG.\n\n\n \n\n\nIt is a great workaround for most situations. You will have to determine the browsers you want or need to support and consider performance issues to decide which method is best for you.\n\nSo it can be used in HTML. Why?\n\nThere are two compelling reasons why vector graphics in the form of icons and symbols are going to be important on the web. With higher resolution screens, going from 72dpi to 200, 300, even over 400dpi, your rasterized icons are looking a little too blocky. As we zoom and print, we expect the visuals on the site to also stay smooth and crisp.\n\nThe other main reason vector graphics are useful is scaling. As responsive websites become the norm, we need a way to dynamically readjust the heights, widths and styles of various elements. SVG handles this perfectly, since vectors remain smooth when changing size.\n\nSVG files are text-based, so they\u2019re small and can be gzipped nicely. There are also techniques for creating SVG sprites to further squeeze out performance gains. But SVG really shines when you begin to couple it with JavaScript. Since SVG elements are part of the DOM, they can be interacted with just like any other element you are used to.\n\nThe folks at Vox Media had an ingenious little trick with their SVG for a Playstation and Xbox One reviews. I\u2019ve used the same technique for the 24 ways example. Vox Media spent a lot of time creating SVG line art of the two consoles, but once in place the artwork scaled and resized beautifully. \n\nThey still had another trick up their sleeves. In their example, they knew each console was line art, so they used SVG\u2019s line dash property to simulate the lines being drawn by animating the growth of the line by small percentage increments until the lines were complete.\n\nThis is a great example of a situation where the alternatives wouldn\u2019t be as straightforward to implement. Using an animated GIF would create a heavy file since it would need to contain all the frames of the animation at a large size to permit scaling; even then, smooth aliasing would be lost. canvas and plenty of JavaScript would be another alternative, but this is a rasterized format. It would need be redrawn at each scale, which is certainly possible, but smoothness would be lost when zooming or printing.\n\nThe HTML, SVG and JavaScript for this example is less than 4KB! Let\u2019s have a quick look at the code:\n\n\n\nFirst, we need to initialize a few variables to set the current frame, the number of frames, how fast the animation will run, and we get each of the paths based on their IDs. With those paths, we set the dash and dash offset.\n\npath[i].style.strokeDasharray = l + ' ' + l; \npath[i].style.strokeDashoffset = l;\n\nWe start the line as a dash, which effectively makes it blank or invisible.\n\nNext, we move to the draw() function. This is where the magic happens. We want to increment the frame to move us forward in the animation and check it\u2019s not finished. If it continues, we then take a percentage of the distance based on the frame and then set the dash offset to this new percentage. This gives the illusion that the line is being drawn. Then we have an animation callback, which starts the draw process over again.\n\nThat\u2019s it! It will work with any SVG element that you can draw.\n\nLibraries to get you started\n\nIf you aren\u2019t sure where to start with SVG, there are several libraries out there to help. They also abstract all browser compatibility issues to make your life easier.\n\n\n\tRapha\u00ebl\n\tSnap.svg\n\tsvg.js\n\n\nYou can also get most vector applications to export SVG. This means that you can continue your normal workflows, but instead of flattening the image as a PNG or bringing it over to Photoshop to rasterize, you can keep all your hard work as vectors and reap the benefits of SVG.", "year": "2013", "author": "Brian Suda", "author_slug": "briansuda", "published": "2013-12-07T00:00:00+00:00", "url": "https://24ways.org/2013/animating-vectors-with-svg/", "topic": null} {"rowid": 89, "title": "Direction, Distance and Destinations", "contents": "With all these new smartphones in the hands of lost and confused owners, we need a better way to represent distances and directions to destinations. The immediate examples that jump to mind are augmented reality apps which let you see another world through your phone\u2019s camera. While this is interesting, there is a simpler way: letting people know how far away they are and if they are getting warmer or colder. \n\nIn the app world, you can easily tap into the phone\u2019s array of sensors such as the GPS and compass, but what people rarely know is that you can do the same with HTML. The native versus web app debate will never subside, but at least we can show you how to replicate some of the functionality progressively in HTML and JavaScript.\n\nIn this tutorial, we\u2019ll walk through how to create a simple webpage listing distances and directions of a few popular locations around the world. We\u2019ll use JavaScript to access the device\u2019s geolocation API and also attempt to access the compass to get a heading. Both of these APIs are documented, to be included in the W3C geolocation API specification, and can be used on both desktop and mobile devices today.\n\nTo get started, we need a list of a few locations around the world. I have chosen the highest mountain peak on each continent so you can see a diverse set of distances and directions. \n\n\n\t\t\n\t\t\tMountain \n\t\t\t\u00b0Latitude \n\t\t\t\u00b0Longitude \n\t\t\n\t\t\n\t\t\tKilimanjaro\n\t\t\t-3.075833\n\t\t\t37.353333\n\t\t\n\t\t\n\t\t\tVinson Massif\n\t\t\t-78.525483\n\t\t\t-85.617147\n\t\t\n\t\t\n\t\t\tPuncak Jaya\n\t\t\t-4.078889\n\t\t\t137.158333\n\t\t\n\t\t\n\t\t\tEverest\n\t\t\t27.988056\n\t\t\t86.925278\n\t\t\n\t\t\n\t\t\tElbrus\n\t\t\t43.355\n\t\t\t42.439167\n\t\t\n\t\t\n\t\t\tMount McKinley\n\t\t\t63.0695\n\t\t\t-151.0074\n\t\t\n\t\t\n\t\t\tAconcagua\n\t\t\t-32.653431\n\t\t\t-70.011083\n\t\t\n\n\nSource: Wikipedia \n\nWe can put those into an HTML list to be styled and accessed by JavaScript to create some distance and directions calculations.\n\nThe next thing we need to do is check to see if the browser and operating system have geolocation support. To do this we test to see if the function is available or not using a single JavaScript if statement.\n\n\n\nThe if statement will be false if geolocation support is not present, and then it is up to you to do something else instead as a fallback. For this example, we\u2019ll do nothing since our page should work as is and only get progressively better if more functionality is available. \n\nThe if statement will be true if there is support and therefore will continue inside the curly brackets to try to get the location. This should prompt the reader to accept or deny the request to get their location. If they say no, the second function callback is processed, in this case a function called geo_error; whereas if the location is available, it fires the geo_success function callback.\n\nThe function geo_error(){ } isn\u2019t that exciting. You can handle this in any way you see fit. The success function is more interesting. We get a position object passed into the function which contains a series of exciting attributes, namely the latitude and longitude of the device\u2019s current location.\n\nfunction geo_success(position){\n\tgLat = position.coords.latitude;\n\tgLon = position.coords.longitude;\n}\n\nNow, in the variables gLat and gLon we have the user\u2019s approximate geographical position. We can use this information to start to calculate some distances between where they are and all the destinations.\n\nAt the time of writing, you can also get position.coords.heading, but on Windows and iOS devices this returned NULL. In the future, if and when this is supported, this is also where you can easily grab the compass information.\n\nInside the geo_success function, we want to loop through the HTML to get all of the mountain peaks\u2019 latitudes and longitudes and compute the distance.\n\n...\n$('.geo').each(function(){\n\t// Get the lat/lon from the HTML\n\ttLat = $(this).find('.lat').html()\n\ttLon = $(this).find('.lon').html()\n\n\t// compute the distances between the current location and this points location\n\tdist = distance(tLat,tLon,gLat,gLon);\n\n\t// set the return values into something useful\n\td = parseInt(dist[0]*10)/10;\n\ta = parseFloat(dist[1]);\n\n\t// display the value in the HTML and style the arrow\n\t$(this).find('.distance').html(d+' km away');\n\t$(this).find('.direction').css('-webkit-transform','rotate(-' + a + 'deg)');\n\n\t// store the arc for later use if compass is available\n\t$(this).attr('data-arc',a);\n}\n\nIn the variable d we have the distance between the current location and the location of the mountain peak based on the Haversine Formula. The variable a is the arc, which has a value from 0 to 359.99. This will be useful later if we have compass support. Given these two values we have a distance and a heading to style the HTML.\n\nThe next thing we want to do is check to see if the device has a compass and then get access to the the current heading. As we\u2019ll see, there are several ways to do this, some of which work on certain devices but not others. The W3C geolocation spec says that, along with the coordinates, there are several other attributes: accuracy; altitude; and heading. Heading is the direction to true north, which is different than magnetic north! WebKit and Windows return NULL for the heading value, but WebKit has an experimental method to fetch the heading. If you get into accessing these sensors, you\u2019ll have to try to catch a few of these methods to finally get a value. Assuming you do, we can move on to the more interesting display opportunities.\n\nIn an ideal world, this would succeed and set a variable we\u2019ll call compassHeading to get a value between 0 and 359.99 degrees. Now we know which direction north is, we also know the direction relative to north of the path to our destination, so we can can subtract the two values to get an arrow to display on the screen. But we\u2019re not finished yet: we also need to get the device\u2019s orientation (landscape or portrait) and subtract the correct amount from the angle for the arrow. Once we have a value, we can use CSS to rotate the arrow the correct number of degrees.\n\n-webkit-transform: rotate(-180deg)\n\nNot all devices support a standard way to access compass information, so in the meantime we need to use a work around. On iOS, you can use the experimental event method e.webkitCompassHeading. We want the compass to update in real time as the device is moved around, so we\u2019ll put this inside an event listener.\n\nwindow.addEventListener('deviceorientation', function(e) {\n\t// Loop through all the locations on the page\n\t$('.geo').each(function(){\n\t\t// get the arc value from north we computed and stored earlier\n\t\tdestination_arc = parseInt($(this).attr('data-arc'))\n\t\tcompassHeading = e.webkitCompassHeading + window.orientation + destination_arc;\n\t\t// find the arrow element and rotate it accordingly\n\t\t$(this).find('.direction').css('-webkit-transform','rotate(-' + compassHeading + 'deg)');\t\t\n\t}\n}\n\nAs the device is rotated, the compass arrow will constantly be updated. If you want to see an example, you can have a look at this page which shows the distances to all the peaks on each continent.\n\nWith progressive enhancement, we slowly layer on additional functionality as we go. The reader will first see the list of locations with a latitude and longitude. If the device is capable and permissions allow, it will then compute the distance. If a compass is available, with the correct permissions it will then add the final layer which is direction.\n\nYou should consider this code a stub for your projects. If you are making a hyperlocal webpage with restaurant locations, for example, then consider adding these features. Knowing not only how far away a place is, but also the direction can be hugely important, and since the compass is always active, it acts as a guide to the location. \n\nFuture developments\n\nImprovements to this could include setting a timer and recalling the navigator.geolocation.getCurrentPosition() function and updating the distances. I chose very distant mountains so kilometres made sense, but you can divide again by 1,000 to convert to metres if you are dealing with much nearer places. Walking or driving would change the distances so the ability to refresh would be important. \n\nIt is outside the scope of this article, but if you manage to get this HTML to work offline, then you can make a nice web app which sits on your devices\u2019 homescreens and works even without an internet connection. This could be ideal for travellers in an unknown city looking for your destination. Just with offline storage, base64 encoding and data URIs, it is possible to embed plenty of design and functionality into a small offline webpage.\n\nNow you know how to use JavaScript to look up a destination\u2019s location and figure out the distance and direction \u2013 never get lost again.", "year": "2012", "author": "Brian Suda", "author_slug": "briansuda", "published": "2012-12-19T00:00:00+00:00", "url": "https://24ways.org/2012/direction-distance-and-destinations/", "topic": "code"} {"rowid": 100, "title": "Moo'y Christmas", "contents": "A note from the editors: Moo has changed their API since this article was written.\n \n \n \n As the web matures, it is less and less just about the virtual world. It is becoming entangled with our world and it is harder to tell what is virtual and what is real. There are several companies who are blurring this line and make the virtual just an extension of the physical. Moo is one such company. \n\nMoo offers simple print on demand services. You can print business cards, moo mini cards, stickers, postcards and more. They give you the ability to upload your images, customize them, then have them sent to your door. Many companies allow this sort of digital to physical interaction, but Moo has taken it one step further and has built an API. \n\nPrintable stocking stuffers \n\nThe Moo API consists of a simple XML file that is sent to their servers. It describes all the information needed to dynamically assemble and print your object. This is very helpful, not just for when you want to print your own stickers, but when you want to offer them to your customers, friends, organization or community with no hassle. Moo handles the check-out and shipping, all you need to do is what you do best, create! \n\nNow using an API sounds complicated, but it is actually very easy. I am going to walk you through the options so you can easily be printing in no time. \n\nBefore you can begin sending data to the Moo API, you need to register and get an API key. This is important, because it allows Moo to track usage and to credit you. To register, visit http://www.moo.com/api/ and click \u201cRequest an API key\u201d. \n\nIn the following examples, I will use {YOUR API KEY HERE} as a place holder, replace that with your API key and everything will work fine. \n\nFirst thing you need to do is to create an XML file to describe the check-out basket. Open any text-editor and start with some XML basics. Don\u2019t worry, this is pretty simple and Moo gives you a few tools to check your XML for errors before you order. \n\n \n \n\t \n\t\t 0.7\n\t\t {YOUR API KEY HERE}\n\t\t build\n\t\t http://www.example.com/return.html\n\t\t http://www.example.com/fail.html\n\t \n\t \n\t ...\n\t \n\n\nMuch like HTML\u2019s and , Moo has created and elements all wrapped in a element. \n\nThe element contains a few pieces of information that is the same across all the API calls. The element describes which version of the API is being used. This is more important for Moo than for you, so just stick with \u201c0.7\u201d for now. \n\nThe allows Moo to track sales, referrers and credit your account. \n\nThe element can only take \u201cbuild\u201d so that is pretty straight forward. The and elements are URLs. These are optional and are the URLs the customer is redirected to if there is an error, or when the check out process is complete. This allows for some basic branding and a custom \u201cthank you\u201d page which is under your control. That\u2019s it for the element, pretty easy so far! \n\nNext up is the element. What goes inside here describes what is to be printed. There are two possible elements, we can put or we can put directly inside . They work in a similar ways, but they drop the customer into different parts of the Moo checkout process. \n\nIf you specify then you send the customer straight to the Moo payment process. If you specify then you send the customer one-step earlier where they are allowed to pick and choose some images, remove the ones they don\u2019t like, adjust the crop, etc. The example here will use but with a little bit of homework you can easily adjust to if you desire. \n\n... \n \n\t sticker \n\t \n\t\t http://example.com/images/christmas1.jpg \n\t \n \n...\n\nInside the element, we can see there are two basic piece of information. The type of product we want to print, and the images that are to be printed. The element can take one of five options and is required! The possibilities are: minicard, notecard, sticker, postcard or greetingcard. We\u2019ll now look at two of these more closely. \n\nMoo Stickers \n\nIn the Moo sticker books you get 90 small squarish stickers in a small little booklet. \n\n\n\nThe simplest XML you could send would be something like the following payload:\n\n...\n\n\t\n\t\tsticker\n\t\t\n\t\t\thttp://example.com/image1.jpg\n\t\t\n\t\t\n\t\t\thttp://example.com/image2.jpg\n\t\t\n\t\t\n\t\t\thttp://example.com/image3.jpg\n\t\t\n\t\n\n...\n\nThis creates a sticker book with only 3 unique images, but 30 copies of each image. The Sticker books always print 90 stickers in multiples of the images you uploaded. That example only has 3 elements, but you can easily duplicate the XML and send up to 90. The should be the full path to your image and the image needs to be a minimum of 300 pixels by 300 pixels.\n\nYou can add more XML to describe cropping, but the simplest option is to either, let your customers choose or to pre-crop all your images square so there are no issues.\n\nThe full XML you would post to the Moo API to print sticker books would look like this:\n\n \n \n\t\n\t\t0.7\n\t\t{YOUR API KEY HERE}\n\t\tbuild\n\t\thttp://www.example.com/return.html\n\t\thttp://www.example.com/fail.html\n\t\n\t\n\t\t\n\t\t\tsticker\n\t\t\t\n\t\t\t\thttp://example.com/image1.jpg\n\t\t\t\n\t\t\t\n\t\t\t\thttp://example.com/image2.jpg\n\t\t\t\n\t\t\t\n\t\t\t\thttp://example.com/image3.jpg\n\t\t\t\n\t\t\n\t \n\n\nMini-cards \n\nThe mini-cards are the small cute business cards in 14\u00d735 dimensions and come in packs of 100. \n\n\n\nSince the mini-cards are print on demand, this allows you to have 100 unique images on the back of the cards.\n\nJust like the stickers example, we need the same XML setup. The element and elements will be the same as before. The part you will focus on is the section. \n\nSince you are sending along specific information, we can\u2019t use the option any more. Switch this to which has a child of , which in turn has a and . This might seem like a lot of work, but once you have it set up you won\u2019t need to change it.\n\n...\n\n\t\n\t\t\n\t\t\tminicard\n\t\t\t\n\t\t\t\t...\n\t\t\t\n\t\t\n\t\n\n...\n\nSo now that we have the basic framework, we can talk about the information specific to minicards. Inside the element, you will have one for each card. Much like before, this contains a way to describe the image. Note that this time the element is called , not images plural. \n\nInside the element you have a which points to where the image lives and a . The should just be set to \u2018variable\u2019. You can pass crop information here instead, but we\u2019re going to keep it simple for this tutorial. If you are interested in how that works, you should refer to the official API documentation.\n\n...\n\n\t\n\t\thttp://example.com/image1.jpg\n\t\tvariable\n\t\n\n...\n\nSo far, we have managed to build a pack of 100 Moo mini-cards with the same image on the front. If you wanted 100 different images, you just need to replicate this snippit, 99 more times.\n\nThat describes the front design, but the flip-side of your mini-cards can contain 6 lines of text, which is customizable in a variety of colors, fonts and styles.\n\nThe API allows you to create different text on the back of each mini-card, something the web interface doesn\u2019t implement. To describe the text on the mini-card we need to add a element inside the element. If you skip this element, the back of your mini-card will just be blank, but that\u2019s not very festive!\n\nInside the element, we need to describe the type of text we want to format, so we add a element, which in turn contains all the lines of text. Each of Moo\u2019s printed products take different numbers of lines of text, so if you are not planning on making mini-cards, be sure to consult the documentation.\n\nFor mini-cards, we can have 6 distinct lines, each with their own style and layout. Each line is represented by an element which has several optional children. The tells which line of the 6 to print the text one. The is the text you want to print and it must be shorter than 38 characters. The element is false by default, but if you want your text bolded, then add this and set it to true. \n\nThe element is also optional. By default it is set to align left. You can also set this to right or center if you desirer. The element takes one of 3 types, modern, traditional or typewriter. The default is modern. Finally, you can set the , yes that\u2019s color with a \u2018u\u2019, Moo is a British company, so they get to make the rules. When you start a print on demand company, you can spell it however you want. The element takes a 6 character hex value with a leading #.\n\n\n\t...\n\t\n\t\t\n\t\t\t\n\t\t\t\t(1-6)\n\t\t\t\tString, I must be less than 38 chars!\n\t\t\t\ttrue\n\t\t\t\tleft\n\t\t\t\tmodern\n\t\t\t\t#ff0000 \n\t\t\t\n\t\t\n\t\n\n\nIf you combine all of this into a mini-card request you\u2019d get this example:\n\n \n \n\t\n\t\t0.7\n\t\t{YOUR API KEY HERE}\n\t\tbuild\n\t\thttp://www.example.com/return.html\n\t\thttp://www.example.com/fail.html\n\t\n\t\n\t\t\n\t\t\t\n\t\t\t\tminicard\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\thttp://example.com/image1.jpg\n\t\t\t\t\t\t\tvariable\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t1\n\t\t\t\t\t\t\t\tString, I must be less than 38 chars!\n\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t\tleft\n\t\t\t\t\t\t\t\tmodern\n\t\t\t\t\t\t\t\t#ff0000 \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t \n\n\nNow you know how to construct the XML that describes what to print. Next, you need to know how to send it to Moo to make it happen!\n\nPosting to the API\n\nSo your XML is file ready to go. First thing we need to do is check it to make sure it\u2019s valid. Moo has created a simple validator where you paste in your XML, and it alerts you to problems.\n\nWhen you have a fully valid XML file, you\u2019ll want to send that to the Moo API. There are a few ways to do this, but the simplest is with an HTML form. \n\nThis is the sample code for an HTML form with a big \u201cBuy My Stickers\u201d button. Once you know that it is working, you can use all your existing HTML knowledge to style it up any way you like.\n\n
\n\t .... ... \"> \n\t\n
\n\nThis is just a basic
element that submits to the Moo API, http://www.moo.com/api/api.php, when someone clicks the button. There is a hidden input called \u201cxml\u201d which contains the value the XML file we created previously.\n\nFor those of you who need to \u201cview source\u201d to fully understand what\u2019s happening can see a working version and peek under the hood.\n\nUsing the API has advantages over uploading the images directly yourself. The images and text that you send via the API can be dynamic. Some companies, like Dopplr, have taken user profiles and dynamic data that changes every minute to generate customer stickers of places that you\u2019ve travelled to or mini-cards with a world map of all the cities you have visited. Every single customer has different travel plans and therefore different sets of stickers and mini-card maps. The API allows for the utmost current information to be printed, on demand, in real-time.\n\nGo forth and Moo\u2019ltiply\n\nSee, making an API call wasn\u2019t that hard was it? You are now 90% of the way to creating anything with the Moo API. With a bit of reading, you can learn that extra 10% and print any Moo product. Be on the lookout in 2009 for the official release of the 1.0 API with improvements and some extras that were not available when this article was written.\n\nThis article is released under the creative-commons attribution share-a-like license. That means you are free to re-distribute it, mash it up, translate it and otherwise re-using it ways the author never considered, in return he only asks you mention his name.\n\n\nThis work by Brian Suda is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.", "year": "2008", "author": "Brian Suda", "author_slug": "briansuda", "published": "2008-12-19T00:00:00+00:00", "url": "https://24ways.org/2008/mooy-christmas/", "topic": "code"} {"rowid": 160, "title": "Tracking Christmas Cheer with Google Charts", "contents": "A note from the editors: Since this article was written Google has retired the Charts API.\n \n \n \n Let\u2019s get something out in the open: I love statistics. As an informatician I can\u2019t get enough graphs, charts, and numbers. So you can imagine when Google released their Charts API I thought Christmas had come early. I immediately began to draw up graphs for the holiday season using the new API; and using my new found chart-making skills I\u2019ll show you what you can and can\u2019t do with Google Charts.\n\nMummy, it\u2019s my first chart\n\nThe Google Charts API allows you to send data to Google; in return they give you back a nicely-rendered graph. All the hard work is done on Google\u2019s servers \u2014 you need only reference an image in your HTML. You pass along the data \u2014 the numbers for the charts, axis labels, and so on \u2014 in the query string of the image\u2019s URL. If you want to add charts to your blog or web site, there\u2019s probably no quicker way to get started.\n\nHere\u2019s a simple example: if we add the following line to an HTML page:\n\n\n\nThen we\u2019ll see the line graph in Figure 1 appear in our page. That graph is hosted on Google\u2019s own server1: http://chart.apis.google.com/.\n\nFigure 1: A simple example of a line graph created with Google Charts.\n\nIf you look at the URL used in the example you\u2019ll notice we\u2019re passing some parameters along in the query string (the bit after the question mark). The query string looks like this:\n\ncht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008\n\nIt\u2019s contains everything Google Charts needs to draw the graph. There are three parameters in the query string:\n\n\n\tcht; this specifies the type of chart Google Charts will generate (in this case, lc is a line chart).\n\tchs, the value of which is 200x125; this defines the chart\u2019s size (200 pixels wide by 125 pixels high).\n\tchd, the value of which is s:ZreelPuevfgznf2008; this is the actual chart data, which we\u2019ll discuss in more detail later.\n\n\nThese three parameters are the minimum you need to send to Google Charts in order to create a chart. There are lots more parameters you can send too (giving you more choice over how a chart is displayed), but you have to include at least these three before a chart can be created. Using these three parameters you can create pie charts, scatter plots, Venn diagrams, bar charts (and more) up to 1,000 pixels wide or 1,000 pixels high (but no more than 300,000 pixels in total).\n\nChristmas pie\n\nAfter I discovered the option to create a pie chart I instantly thought of graphing all the types of food and beverages that I\u2019ll consume at this year\u2019s Christmas feast. I can represent each item as a percentage of all the food on a pie chart (just thinking about that makes me hungry).\n\nBy changing the value of the cht parameter in the image\u2019s query string I can change the chart type from a line chart to a pie chart. Google Charts offers two different types of pie chart: a fancy three-dimensional version and a two-dimensional overhead version. I want to stick with the latter, so I need to change cht=lc to cht=p (the p telling Google Charts to create a pie chart; if you want the three-dimensional version, use cht=p3). As a pie chart is circular I also need to adjust the size of the chart to make it square. Finally, it would be nice to add a title to the graph. I can do this by adding the optional parameter, chtt, to the end of the image URL. I end up with the chart you see in Figure 2.\n\nFigure 2: Pie chart with a title.\n\nTo add this chart to your own page, you include the following (notice that you can\u2019t include spaces in URLs, so you need to encode them as plus-signs.):\n\n\n\nOk, that\u2019s great, but there are still two things I want to do before I can call this pie chart complete. First I want to label each slice of the pie. And second I want to include the proper data (at the moment the slices are meaningless). If 2007 is anything like 2006, the break down will be roughly as follows:\n\n\n\t\t\n\t\t\tEgg nog\n\t\t\t10%\n\t\t\n\t\t\n\t\t\tChristmas Ham\n\t\t\t20%\n\t\t\n\t\t\n\t\t\tMilk (not including egg nog)\n\t\t\t8%\n\t\t\n\t\t\n\t\t\tCookies\n\t\t\t25%\n\t\t\n\t\t\n\t\t\tRoasted Chestnuts\n\t\t\t5%\n\t\t\n\t\t\n\t\t\tChocolate\n\t\t\t3%\n\t\t\n\t\t\n\t\t\tVarious Other Beverages\n\t\t\t15%\n\t\t\n\t\t\n\t\t\tVarious Other Foods\n\t\t\t9%\n\t\t\n\t\t\n\t\t\tSnacks\n\t\t\t5%\n\t\t\n\n\nI have nine categories of food and drink to be tracked, so I need nine slice labels. To add these to the chart, I use the chl parameter. All nine labels are sent in one value; I use the vertical-pipe character, |, to separate them. So I need to append the following to the query string:\n\nchl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks\n\nNext I need to add the corresponding percentage values to the chart labels. Encoding the chart data is the trickiest part of the Google Charts API \u2014 but by no means complicated. There are three different ways to encode your data on a chart. As I\u2019m only dealing with small numbers, I\u2019m going to use what Google calls simple encoding.\n\nSimple encoding offers a sixty-two value spectrum in which to represent data. Remember the mandatory option, chd, from the first example? The value for this is split into two parts: the type of encoding and the graph data itself. These two parts are separated with a colon. To use simple encoding, the first character of the chd option must be a lower case s. Follow this with a colon and everything after it is considered data for the graph.\n\nIn simple encoding, you have sixty-two values to represent your data. These values are lowercase and uppercase letters from the Latin alphabet (fifty-two characters in total) and the digits 0 to 9. Each letter of the alphabet represents a single number: A equals 0, B equals 1, and so on up to Z, which equals 25; a equals 26, b equals 27, and so on up to z, which equals 51. The ten digits represent the numbers 52 to 61: 0 equals 52, 1 equals 53, and 9 equals 61.\n\nIn the previous two examples we used the string ZreelPuevfgznf2008 as our chart data; the Z is equal to 25, the r is equal to 42, the e is equal to 30, and so on. I want to encode the percentage values 10, 20, 8, 25, 5, 3, 15, 9 and 5, so in simple encoding I would use the string KUIZFDPJF.\n\nIf you think figuring this out for each chart may make your head explode, don\u2019t worry: help is out there.\n\nDo you remember I said I needed to change the image dimensions to be square, to accommodate the pie chart? Well now I\u2019m including labels I need even more room. And as I\u2019m in a Christmassy mood I\u2019m going to add some festive colours too.\n\nThe optional chco parameter is used to change the chart color. You set this using the same hexadecimal (\u201chex\u201d) notation found in CSS. So let\u2019s make our pie chart green by adding chco=00AF33 (don\u2019t start it with a hash character as in CSS) to the image URL. If we only specify one hex colour for the pie chart Google Charts will use shades of that colour for each of the slices. To choose your own colours, pass a comma separated list of colours. The \u201cMilk\u201d and \u201cCookies\u201d slices were consumed together, so we can make those two slices more of a redish colour. I\u2019ll use shades of green for the other slices. My chco parameter now looks like this:\n\nchco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC.\n\nAfter all this, I\u2019m left with the following URL:\n\nhttp://chart.apis.google.com/chart?chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC&chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=600x300&chd=s:KUIZFDPJF\n\nWhat does that give us? I\u2019m glad you asked. I have the rather beautiful 600-pixel wide pie chart you see in Figure 3.\n\nFigure 3: A Christmassy pie chart with labels.\n\nBut I don\u2019t like pie charts\n\nThe pie chart was invented by the Scottish polymath William Playfair in 1801. But not everyone is as excited by pie charts as wee Billy, so if you\u2019re an anti-pie-chartist, what can you do?\n\nYou can easily reuse the same data but display it as a bar graph in a snap. The first thing we need to do is change the value of the cht parameter from p to bhg. This creates a horizontal bar graph (you can request a vertical bar graph using bvg). The data and labels all remain the same, but we need to decide where the labels will appear. I\u2019ll talk more about how to do all this in the next section. \n\nIn Figure 4 you\u2019ll see the newly-converted bar graph. The URL for the graph is:\n\nhttp://chart.apis.google.com/chart?cht=bhg&chs=600x300&chd=s:KUIZFDPJF&chxt=x,y&chtt=Food+and+Drink+Consumed+Christmas+2007&chxl=1:|Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chco=00AF33\n\nFigure 4: The pie chart from Figure 3 represented as a bar chart.\n\nTwo lines, one graph\n\nPie charts and bar charts are interesting, but what if I want to compare last year\u2019s Christmas cheer with this year\u2019s? That sounds like I\u2019ll need two lines on one graph.\n\nThe code is much the same as the previous examples; the most obvious difference is I need to set up the chart as a line graph. Creating some dummy values for the required parameters, I end up with:\n\n\n\nThe chs=800x300 sets the dimensions of the new chart, while cht=lxy describes the type of chart we are using (in this case a line chart with x and y co-ordinates). For the chart data I\u2019m going to demostrate a different encoding, text encoding. To use this I start the value of the chd parameter with \u201ct:\u201d instead of \u201cs:\u201d, and follow it with a list of x coordinates, a vertical pipe, |, and a list of y coordinates. Given the URL above, Google Charts will render the chart shown in Figure 5.\n\nFigure 5: A simple line graph with x and y co-ordinates.\n\nTo make this graph a little more pleasing to the eye, I can add much the same as I did to the pie chart. I\u2019ll add a chart title. Maybe something like \u201cProjected Christmas Cheer for 2007\u201d. Just as before I would add a chtt parameter to the image URL:\n\n&chtt=Projected+Christmas+Cheer+for+2007\n\nNext, let\u2019s add some labels on the y axis to represent a scale from 0 to 100. On the x axis let\u2019s label for the most important days of December. To do this I need to use the chart axis type parameter, chxt. This allows us to specify the axes and associate some labels with them. As I\u2019m only interested in the y-axis (to the left of the chart) and the x-axis (below the chart), we add chxt=x,y to our image URL.\n\nNow I need my label data. This is slightly more tricky because I want the data evenly spaced without labelling every item. The parameter for labels is chxl, the chart axis label. You match a label to an axis by using a number. So 0:Label1 is the zero index of chxt \u2014 in this case the x-axis. 1:Label2 is the first index of chxt \u2014 the y-axis. The order of these parameters or labels doesn\u2019t matter as long as you associate them to their chxt correctly.\n\nThe next thing to know about chxl is that you can add an empty label. Labels are separated by vertical pipe; if you don\u2019t put any text in a label, you just leave the two vertical pipes empty (\u201c||\u201d) and Google Charts will allocate space but no label.\n\nFor our vertical y axis, we want to label only 50% and 100% on the graph and plot them in their respective places. Since the y-axis is the second item, 1: (remember to start counting at zero), we add ten spaces to our image URL, chxl=1:||||||50|||||100 This will output the 50 halfway and the 100 at the top; all the other spaces will be empty.\n\nWe can do the same thing to get specific dates along the x-axis as well. Let\u2019s add the 1st of December, St. Nick\u2019s Day (the 6th), Christmas Day, Boxing Day (a holiday common in the UK and the Commonwealth, on the 26th), and the final day of the month, the 31st. Since this is the x-axis I\u2019ll use 0: as a reference in the chxt parameter tell Google Charts which axis to label. In full, the chxl parameter now looks like:\n\nchxl=1:||||||50|||||100|0:|Dec+1st|||||6th||||10th|||||15th|||||20th|||||25th|26th|||||Dec+31st\n\nThat\u2019s pretty.\n\nBefore we begin to graph our data, I\u2019ll do one last thing: add some grid lines to the chart so to better connect the data to the labels. The parameter for this is chg, short for chart grid lines. The parameter takes four comma-separated arguments. The first is the x-axis spacing for the grid. I have thirty-one days, so I need thirty vertical lines. The chart is 100% wide, so 3.33 (100 divided by 30) is the required spacing.\n\nAs for the y-axis: the axis goes up to 100% but we probably only need to have a horizontal line every 10%, so the required spacing is 10 (100 divided by 10). That is the second argument.\n\nThe last two arguments control the dash-style of the grid-lines. The first number is the length of the line dash and the second is the space between the dashes. So 6,3 would mean a six-unit dash with a three-unit space. I like a ratio of 1,3 but you can change this as you wish. Now that I have the four arguments, the chg parameter looks like:\n\nchg=3.333,10,1,3\n\nIf I add that to the chart URL I end up with:\n\nhttp://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3\n\nWhich results in the chart shown in Figure 6.\n\nFigure 6: Chart ready to receive the Christmas cheer values.\n\nReal data\n\nNow the chart is ready I can add historical data from 2006 and current data from 2007.\n\nHaving a look at last year\u2019s cheer levels we find some highs and lows through-out the month:\n\n\n\t\t\n\t\t\tDec 1st\n\t\t\tAdvent starts; life is good\n\t\t\t30%\n\t\t\n\t\t\n\t\t\tDec 6th\n\t\t\tSt. Nick\u2019s Day, awake to find good things in my shoes\n\t\t\t45%\n\t\t\n\t\t\n\t\t\tDec 8th\n\t\t\tWent Christmas carolling, nearly froze\n\t\t\t20%\n\t\t\n\t\t\n\t\t\tDec 10th\n\t\t\tChristmas party at work, very nice dinner\n\t\t\t50%\n\t\t\n\t\t\n\t\t\tDec 18th\n\t\t\tPanic Christmas shopping, hate rude people\n\t\t\t15%\n\t\t\n\t\t\n\t\t\tDec 23rd\n\t\t\tOff Work, home eating holiday food\n\t\t\t80%\n\t\t\n\t\t\n\t\t\tDec 25th\n\t\t\tOpened presents, good year, but got socks again from Grandma\n\t\t\t60%\n\t\t\n\t\t\n\t\t\tDec 26th\n\t\t\tBoxing Day; we\u2019re off and no one knows why\n\t\t\t70%\n\t\t\n\t\t\n\t\t\tDec 28th\n\t\t\tThird day of left overs\n\t\t\t40%\n\t\t\n\t\t\n\t\t\tDec 29th\n\t\t\tProcured some fireworks for new years\n\t\t\t55%\n\t\t\n\t\t\n\t\t\tDec 31st\n\t\t\tNew Year\u2019s Eve\n\t\t\t80%\n\t\t\n\n\nSince I\u2019m plotting data for 2006 and 2007 on the same graph I\u2019ll need two different colours \u2014 one for each year\u2019s line \u2014 and a key to denote what each colour represents. The key is controlled by the chdl (chart data legend) parameter. Again, each part of the parameter is separated by a vertical pipe, so for two labels I\u2019ll use chdl=2006|2007. I also want to colour-code them, so I\u2019ll need to add the chco as I did for the pie chart. I want a red line and a green line, so I\u2019ll use chco=458B00,CD2626 and add this to the image URL.\n\nLet\u2019s begin to plot the 2006 data on the Chart, replacing our dummy data of chd=t:0,100|0,100 with the correct information. The chd works by first listing all the x coordinates (each separated by a comma), then a vertical pipe, and then all the y coordinates (also comma-separated). The chart is 100% wide, so I need to convert the days into a percentage of the month.\n\nThe 1st of December is 0 and the 31st is 100. Everything else is somewhere in between. Our formula is:\n\n(d \u2013 1) \u00d7 100 \u00f7 (31 \u2013 1)\n\nWhere d is the day of the month. The formula states that each day will be printed every 3.333 units; so the 6th of December will be printed at 16.665 units. I can repeat the process for the other dates listed to get the following x coordinates: 0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7. The y axis coordinates are easy because our scale is 100%, just like our rating, so we can simply copy them across as 30,45,20,50,15,80,60,70,40,55,80. This gives us a final chd value of:\n\nchd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80\n\nOnto 2007: I can put the data for the month so far to see how we are trending.\n\n\n\t\t\n\t\t\tDec 1st\n\t\t\tChristmas shopping finished already\n\t\t\t50%\n\t\t\n\t\t\n\t\t\tDec 4th\n\t\t\tComputer hard disk drive crashed (not Christmas related accident, but put me in a bad mood)\n\t\t\t10%\n\t\t\n\t\t\n\t\t\tDec 6th\n\t\t\tMissed St. Nick\u2019s Day completely due to travelling\n\t\t\t30%\n\t\t\n\t\t\n\t\t\tDec 9th\n\t\t\tDinner with friends before they travel\n\t\t\t55%\n\t\t\n\t\t\n\t\t\tDec 11th\n\t\t\t24ways article goes live\n\t\t\t60%\n\t\t\n\n\nUsing the same system we did for 2006, I can take the five data points and plot them on the chart. The new x axis values will be 0,10,16.7,26.7 and the new y axis 50,10,30,65. We incorporate those into the image URL by appending these values onto the chd parameter we already have, which then becomes:\n\nchd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60\n\nPassing this to Google Charts results in Figure 7.\n\nhttp://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3&chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60&chco=458B00,CD2626&chdl=2006|2007\n\nFigure 7: Projected Christmas cheer for 2006 and 2007.\n\nDid someone mention Edward Tufte?\n\nGoogle Charts are a robust set of chart types that you can create easily and freely using their API. As you can see, you can graph just about anything you want using the line graph, bar charts, scatter plots, venn diagrams and pie charts. One type of chart conspicuously missing from the API is sparklines. Sparklines were proposed by Edward Tufte as \u201csmall, high resolution graphics embedded in a context of words, numbers, images\u201d. They can be extremely useful, but can you create them in Google Charts?\n\nThe answer is: \u201cYes, but it\u2019s an undocumented feature\u201d. (The usual disclaimer about undocumented features applies.)\n\nIf we take our original line graph example, and change the value of the cht parameter from lc (line chart) to lfi (financial line chart) the axis-lines are removed. This allows you to make a chart \u2014 a sparkline \u2014 small enough to fit into a sentence. Google uses the lfi type all throughout the their financial site, but it\u2019s not yet part of the official API.\n\n\n\t\t\n\t\t\tMerryChristmas\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:MerryChristmas\n\t\t\n\t\t\n\t\t\t24ways\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:24ways&chco=999999\n\t\t\n\t\t\n\t\t\tHappyHolidays\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyHolidays&chco=ff0000\n\t\t\n\t\t\n\t\t\tHappyNewYear\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyNewYear&chco=0000ff\n\t\t\n\n\nSummary\n\nThe new Google Charts API is a powerful method for creating charts and graphs of all types. If you apply a little bit of technical skill you can create pie charts, bar graphs, and even sparklines as and when you need them. Now you\u2019ve finished ready the article I hope you waste no more time: go forth and chart!\n\nFurther reading\n\n\n\tGoogle Charts API\n\tMore on Google Charts\n\tHow to handle negative numbers\n\t12 Days of Christmas Pie Chart\n\n\n1 In order to remain within the 50,000 requests a day limit the Google Charts API imposes, chart images on this page have been cached and are being served from our own servers. But the URLs work \u2013 try them!", "year": "2007", "author": "Brian Suda", "author_slug": "briansuda", "published": "2007-12-11T00:00:00+00:00", "url": "https://24ways.org/2007/tracking-christmas-cheer-with-google-charts/", "topic": "ux"} {"rowid": 223, "title": "Calculating Color Contrast", "contents": "Some websites and services allow you to customize your profile by uploading pictures, changing the background color or other aspects of the design. As a customer, this personalization turns a web app into your little nest where you store your data. As a designer, letting your customers have free rein over the layout and design is a scary prospect. So what happens to all the stock text and images that are designed to work on nice white backgrounds? Even the Mac only lets you choose between two colors for the OS, blue or graphite! Opening up the ability to customize your site\u2019s color scheme can be a recipe for disaster unless you are flexible and understand how to find maximum color contrasts.\n\nIn this article I will walk you through two simple equations to determine if you should be using white or black text depending on the color of the background. The equations are both easy to implement and produce similar results. It isn\u2019t a matter of which is better, but more the fact that you are using one at all! That way, even with the craziest of Geocities color schemes that your customers choose, at least your text will still be readable.\n\nLet\u2019s have a look at a range of various possible colors. Maybe these are pre-made color schemes, corporate colors, or plucked from an image.\n\n\n\nNow that we have these potential background colors and their hex values, we need to find out whether the corresponding text should be in white or black, based on which has a higher contrast, therefore affording the best readability. This can be done at runtime with JavaScript or in the back-end before the HTML is served up.\n\nThere are two functions I want to compare. The first, I call \u201950%\u2019. It takes the hex value and compares it to the value halfway between pure black and pure white. If the hex value is less than half, meaning it is on the darker side of the spectrum, it returns white as the text color. If the result is greater than half, it\u2019s on the lighter side of the spectrum and returns black as the text value.\n\nIn PHP:\n\nfunction getContrast50($hexcolor){\n return (hexdec($hexcolor) > 0xffffff/2) ? 'black':'white';\n}\n\nIn JavaScript:\n\nfunction getContrast50(hexcolor){\n return (parseInt(hexcolor, 16) > 0xffffff/2) ? 'black':'white';\n}\n\nIt doesn\u2019t get much simpler than that! The function converts the six-character hex color into an integer and compares that to one half the integer value of pure white. The function is easy to remember, but is naive when it comes to understanding how we perceive parts of the spectrum. Different wavelengths have greater or lesser impact on the contrast.\n\nThe second equation is called \u2018YIQ\u2019 because it converts the RGB color space into YIQ, which takes into account the different impacts of its constituent parts. Again, the equation returns white or black and it\u2019s also very easy to implement.\n\nIn PHP:\n\nfunction getContrastYIQ($hexcolor){\n\t$r = hexdec(substr($hexcolor,0,2));\n\t$g = hexdec(substr($hexcolor,2,2));\n\t$b = hexdec(substr($hexcolor,4,2));\n\t$yiq = (($r*299)+($g*587)+($b*114))/1000;\n\treturn ($yiq >= 128) ? 'black' : 'white';\n}\n\nIn JavaScript:\n\nfunction getContrastYIQ(hexcolor){\n\tvar r = parseInt(hexcolor.substr(0,2),16);\n\tvar g = parseInt(hexcolor.substr(2,2),16);\n\tvar b = parseInt(hexcolor.substr(4,2),16);\n\tvar yiq = ((r*299)+(g*587)+(b*114))/1000;\n\treturn (yiq >= 128) ? 'black' : 'white';\n}\n\nYou\u2019ll notice first that we have broken down the hex value into separate RGB values. This is important because each of these channels is scaled in accordance to its visual impact. Once everything is scaled and normalized, it will be in a range between zero and 255. Much like the previous \u201950%\u2019 function, we now need to check if the input is above or below halfway. Depending on where that value is, we\u2019ll return the corresponding highest contrasting color.\n\nThat\u2019s it: two simple contrast equations which work really well to determine the best readability.\n\nIf you are interested in learning more, the W3C has a few documents about color contrast and how to determine if there is enough contrast between any two colors. This is important for accessibility to make sure there is enough contrast between your text and link colors and the background.\n\nThere is also a great article by Kevin Hale on Particletree about his experience with choosing light or dark themes. To round it out, Jonathan Snook created a color contrast picker which allows you to play with RGB sliders to get values for YIQ, contrast and others. That way you can quickly fiddle with the knobs to find the right balance.\n\nComparing results\n\nLet\u2019s revisit our color schemes and see which text color is recommended for maximum contrast based on these two equations.\n\n\n\nIf we use the simple \u201950%\u2019 contrast function, we can see that it recommends black against all the colors except the dark green and purple on the second row. In general, the equation feels the colors are light and that black is a better choice for the text.\n\n\n\nThe more complex \u2018YIQ\u2019 function, with its weighted colors, has slightly different suggestions. White text is still recommended for the very dark colors, but there are some surprises. The red and pink values show white text rather than black. This equation takes into account the weight of the red value and determines that the hue is dark enough for white text to show the most contrast.\n\nAs you can see, the two contrast algorithms agree most of the time. There are some instances where they conflict, but overall you can use the equation that you prefer. I don\u2019t think it is a major issue if some edge-case colors get one contrast over another, they are still very readable.\n\nNow let\u2019s look at some common colors and then see how the two functions compare. You can quickly see that they do pretty well across the whole spectrum.\n\n\n\nIn the first few shades of grey, the white and black contrasts make sense, but as we test other colors in the spectrum, we do get some unexpected deviation. Pure red #FF0000 has a flip-flop. This is due to how the \u2018YIQ\u2019 function weights the RGB parts. While you might have a personal preference for one style over another, both are justifiable.\n\n\n\nIn this second round of colors, we go deeper into the spectrum, off the beaten track. Again, most of the time the contrasting algorithms are in sync, but every once in a while they disagree. You can select which you prefer, neither of which is unreadable.\n\nConclusion\n\nContrast in color is important, especially if you cede all control and take a hands-off approach to the design. It is important to select smart defaults by making the contrast between colors as high as possible. This makes it easier for your customers to read, increases accessibility and is generally just easier on the eyes. \n\nSure, there are plenty of other equations out there to determine contrast; what is most important is that you pick one and implement it into your system.\n\nSo, go ahead and experiment with color in your design. You now know how easy it is to guarantee that your text will be the most readable in any circumstance.", "year": "2010", "author": "Brian Suda", "author_slug": "briansuda", "published": "2010-12-24T00:00:00+00:00", "url": "https://24ways.org/2010/calculating-color-contrast/", "topic": "code"}