├── LICENSE ├── README.md ├── bower.json └── dpeges.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pascal TOUSSAINT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub version](https://badge.fury.io/gh/pascalz%2Fdpeges.svg)](https://badge.fury.io/gh/pascalz%2Fdpeges) 2 | 3 | # DPE-GES 4 | 5 | A pure javascript utility to generate an SVG graph for DPE and GES diagnostics. 6 | No dependency needed, no need jQuery or RaphaelJS 7 | 8 | **DPE** : Diagnostic de performance énergétique (Energy Performance Diagnostic) 9 | **GES** : Gaz à effet de serre (Greenhouse Gas Emissions) 10 | 11 | ## Installation 12 | 13 | Just copy the dpeges.js file in your scripts folder. 14 | 15 | You can also use bower: 16 | ``` 17 | $ bower install dpeges 18 | ``` 19 | 20 | ## Basic example 21 | 22 | ```html 23 | 24 | 25 | 26 | 27 | GES/DPE basic example 28 | 29 | 30 |
31 |
32 | 33 | 34 | 46 | 47 | 48 | 49 | ``` 50 | 51 | ## Options 52 | 53 | Option name | Description | Required | Default value 54 | ------------- | --------------------------------------------------------------- | -------- | ------------- 55 | domId | The id of the element that will contain the generated SVG image | Yes | 56 | value | The DPE or GES actual value, can be an integer or just a letter | No | 200 57 | width | The width of the generated SVG image | No | 250 58 | height | The height of the generated SVG image | No | 200 59 | shadow | Add shadow to the image | No | false 60 | lang | The language to use (currently supported: 'fr' and 'en') | No | 'fr' 61 | 62 | ## Demo 63 | 64 | http://pascalz.github.io/dpeges/ 65 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dpeges", 3 | "description": "Create an SVG graphic for DPE and GES diagnostics.", 4 | "main": "dpeges.js", 5 | "version": "0.0.4", 6 | "homepage": "https://github.com/Pascalz/dpeges", 7 | "authors": [ 8 | "Pascalz (http://www.pascalz.com)" 9 | ], 10 | "keywords": [ 11 | "DPE", 12 | "GES" 13 | ], 14 | "license": "MIT", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /dpeges.js: -------------------------------------------------------------------------------- 1 | var DpeGes = function () { 2 | 3 | "use strict"; 4 | 5 | function Diag(options) { 6 | 7 | var self = this; 8 | 9 | // Default options is DPE 10 | var defaultOptions = { 11 | width: 250, 12 | height: 200, 13 | value: 200, 14 | header: '', 15 | footer: '', 16 | valuesRange: [ 17 | { min: null, max: 50, color: '#319834', textColor: '#000000', label: 'A' }, 18 | { min: 51, max: 90, color: '#33cc31', textColor: '#000000', label: 'B' }, 19 | { min: 91, max: 150, color: '#cbfc34', textColor: '#000000', label: 'C' }, 20 | { min: 151, max: 230, color: '#fbfe06', textColor: '#000000', label: 'D' }, 21 | { min: 231, max: 330, color: '#fbcc05', textColor: '#000000', label: 'E' }, 22 | { min: 331, max: 450, color: '#fc9935', textColor: '#000000', label: 'F' }, 23 | { min: 451, max: null, color: '#fc0205', textColor: '#ffffff', label: 'G' } 24 | ], 25 | shadow: false, 26 | lang: 'fr', 27 | pad: 5, 28 | shape: 'sharp', 29 | domId: undefined 30 | }; 31 | 32 | self.width = options.width || defaultOptions.width; 33 | self.height = options.height || defaultOptions.height; 34 | 35 | self.value = options.value || defaultOptions.value; 36 | self.shadow = options.shadow || defaultOptions.shadow; 37 | 38 | self.header = options.header || defaultOptions.header; 39 | self.footer = options.footer || defaultOptions.footer; 40 | 41 | //self.options = options; 42 | self.lang = options.lang || defaultOptions.lang; 43 | self.pad = options.pad || defaultOptions.pad; 44 | self.shape = options.shape || defaultOptions.shape; 45 | 46 | self.domId = options.domId || defaultOptions.domId; 47 | 48 | var svgNS = "http://www.w3.org/2000/svg"; 49 | 50 | self.container = document.getElementById(self.domId); 51 | 52 | // Empty container 53 | while (self.container.firstChild) { 54 | self.container.removeChild(self.container.firstChild); 55 | } 56 | 57 | self.score = -1; 58 | 59 | // Get texts and colors for each value in valuesRange 60 | self.getValuesDatas = function () { 61 | 62 | self.values = []; 63 | self.colors = []; 64 | self.textColors = []; 65 | self.labels = []; 66 | 67 | var toTxt = " à "; 68 | switch (self.lang) { 69 | case "fr": 70 | toTxt = " à "; 71 | break; 72 | case "en": 73 | toTxt = " to "; 74 | break; 75 | } 76 | options.valuesRange.forEach(function (value) { 77 | if (value.min === null && value.max !== null) { 78 | self.values.push("≤ " + value.max); 79 | } else if (value.min !== null && value.max !== null) { 80 | self.values.push(value.min + toTxt + value.max); 81 | } else if (value.min !== null && value.max === null) { 82 | self.values.push("> " + (value.min - 1)); 83 | } 84 | self.colors.push(value.color); 85 | self.textColors.push(value.textColor); 86 | self.labels.push(value.label); 87 | }); 88 | }; 89 | 90 | 91 | self.getScore = function () { 92 | try { 93 | options.valuesRange.forEach(function (values) { 94 | self.score++; 95 | if (typeof self.value === 'string') { 96 | if (self.value === values.label) { 97 | throw {}; 98 | } 99 | } else if (values.min === null && values.max !== null) { 100 | if (self.value <= values.max) { 101 | throw {}; 102 | } 103 | } else if (values.min !== null && values.max !== null) { 104 | if (self.value >= values.min && self.value <= values.max) { 105 | throw {}; 106 | } 107 | } else if (values.min !== null && values.max === null) { 108 | if (self.value >= values.min) { 109 | throw {}; 110 | } 111 | } 112 | }); 113 | } catch (e) { 114 | // 115 | } 116 | }; 117 | 118 | self.setAttributes = function (elem, o) { 119 | if (o.fill) { 120 | elem.setAttribute("fill", o.fill); 121 | } 122 | if (o.fontSize) { 123 | elem.setAttribute("font-size", o.fontSize); 124 | } 125 | if (o.fontFamily) { 126 | elem.setAttribute("font-family", o.fontFamily); 127 | } 128 | if (o.textAnchor) { 129 | elem.setAttribute("text-anchor", o.textAnchor); 130 | } 131 | if (o.fontWeight) { 132 | elem.setAttribute("font-weight", o.fontWeight); 133 | } 134 | if (o.strokeWidth) { 135 | elem.setAttribute("stroke-width", o.strokeWidth); 136 | } 137 | if (o.stroke) { 138 | elem.setAttribute("stroke", o.stroke); 139 | } 140 | if (o.opacity) { 141 | elem.setAttribute("opacity", o.opacity); 142 | } 143 | }; 144 | 145 | self.getPath = function (path, options) { 146 | var elem = document.createElementNS(svgNS, "path"); 147 | self.setAttributes(elem, options); 148 | 149 | elem.setAttribute("d", path); 150 | 151 | return elem; 152 | }; 153 | 154 | self.getPolygon = function (points, color) { 155 | var elem = document.createElementNS(svgNS, "polygon"); 156 | elem.setAttribute("style", "fill-opacity: 1;fill: " + color + ";stroke: #000000;" + (self.shadow ? "filter:url(#fs)" : "")); 157 | elem.setAttribute("points", points); 158 | 159 | return elem; 160 | }; 161 | 162 | self.getText = function (text) { 163 | var elem = document.createElementNS(svgNS, "text"); 164 | elem.setAttribute("x", text.x); 165 | elem.setAttribute("y", text.y); 166 | elem.textContent = text.text; 167 | self.setAttributes(elem, text.options); 168 | return elem; 169 | }; 170 | 171 | self.createSVG = function () { 172 | self.getScore(); 173 | self.getValuesDatas(); 174 | 175 | var svg = document.createElementNS(svgNS, "svg"); 176 | svg.setAttribute("style", "overflow: hidden; position: relative;"); 177 | svg.setAttribute("width", self.width); 178 | svg.setAttribute("height", self.height); 179 | svg.setAttribute("version", "1.1"); 180 | svg.setAttribute("viewBox", "0 0 " + self.width + " " + self.height); 181 | svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); 182 | 183 | var desc = document.createElementNS(svgNS, "desc"); 184 | desc.textContent = 'Created by Pascalz (http://pascalz.github.io/dpeges/)'; 185 | svg.appendChild(desc); 186 | var defs = document.createElementNS(svgNS, "defs"); 187 | var filter = document.createElementNS(svgNS, "filter"); 188 | filter.setAttribute("id", "fs"); 189 | //filter.setAttribute("height", "120%"); 190 | 191 | var feGaussianBlur = document.createElementNS(svgNS, "feGaussianBlur"); 192 | feGaussianBlur.setAttribute("in", "SourceAlpha"); 193 | feGaussianBlur.setAttribute("stdDeviation", "1"); 194 | filter.appendChild(feGaussianBlur); 195 | 196 | var feOffset = document.createElementNS(svgNS, "feOffset"); 197 | feOffset.setAttribute("result", "offsetblur"); 198 | feOffset.setAttribute("dx", "1"); 199 | feOffset.setAttribute("dy", "0.5"); 200 | filter.appendChild(feOffset); 201 | 202 | var feMerge = document.createElementNS(svgNS, "feMerge"); 203 | var feMergeNode1 = document.createElementNS(svgNS, "feMergeNode"); 204 | feMerge.appendChild(feMergeNode1); 205 | var feMergeNode2 = document.createElementNS(svgNS, "feMergeNode"); 206 | feMergeNode2.setAttribute("in", "SourceGraphic"); 207 | feMerge.appendChild(feMergeNode2); 208 | filter.appendChild(feMerge); 209 | defs.appendChild(filter); 210 | svg.appendChild(defs); 211 | 212 | var countElem = self.values.length; 213 | 214 | var blocHeight = (self.height - ((countElem + 1) * self.pad)) / countElem; 215 | var blocWidth = (self.width - (2 * self.pad)) - 45; 216 | 217 | var blocPart = ((blocWidth / 3) * 2) / (countElem - 1); 218 | blocWidth = (blocWidth / 3); 219 | 220 | for (var i = 0; i < countElem; i++) { 221 | var x, y, x1, y1, x2, y2, poly; 222 | x = self.pad; 223 | y = ((i * self.pad) + self.pad) + (i * blocHeight); 224 | 225 | switch (self.shape) { 226 | case "sharp": 227 | x1 = ((blocWidth + (blocPart * i)) - (blocHeight / 2)); 228 | 229 | x2 = x + (blocWidth + blocPart * i); 230 | y1 = y + (blocHeight / 2); 231 | 232 | y2 = y + blocHeight; 233 | poly = x + "," + y + " " + 234 | x1 + "," + y + " " + 235 | x2 + "," + y1 + " " + 236 | x1 + "," + y2 + " " + 237 | x + "," + y2 + " " + 238 | x + "," + y; 239 | break; 240 | case "flat": 241 | x1 = x + (blocWidth + blocPart * i); 242 | 243 | y1 = y + blocHeight; 244 | poly = x + "," + y + " " + 245 | x1 + "," + y + " " + 246 | x1 + "," + y1 + " " + 247 | x + "," + y1 + " " + 248 | x + "," + y; 249 | break; 250 | } 251 | 252 | if (self.score === i) { 253 | var sx1 = x - 2; 254 | var sx2 = (self.width - (2 * self.pad)) + 2; 255 | var sy1 = y - 2; 256 | var sy2 = y + blocHeight + 3; 257 | 258 | var scorePath = "M " + sx1 + " " + sy1 + 259 | "L" + sx2 + " " + sy1 + 260 | "L" + sx2 + " " + sy2 + 261 | "L" + sx1 + " " + sy2 + " Z"; 262 | svg.appendChild(self.getPath(scorePath, 263 | { 264 | 'stroke': '#5b5b5b', 265 | 'strokeWidth': 1, 266 | 'fill': "#ffffff", 267 | 'fillOpacity': 0.8 268 | })); 269 | 270 | svg.appendChild(self.getText( 271 | { 272 | x: sx2 - 5, 273 | y: y + blocHeight * 0.9, 274 | text: self.value, 275 | options: { 276 | 'fill': '#000000', 277 | 'fontSize': blocHeight * 0.9, 278 | 'fontWeight': 'bold', 279 | 'fontFamily': "'Arial Narrow', sans-serif", 280 | 'textAnchor': 'end' 281 | } 282 | } 283 | )); 284 | } 285 | 286 | svg.appendChild(self.getPolygon(poly, self.colors[i])); 287 | 288 | var whiteIdx = (self.shape === "sharp") ? 5 : 3; 289 | 290 | svg.appendChild(self.getText( 291 | { 292 | x: x1 - self.pad, 293 | y: y + (blocHeight * 0.8), 294 | text: self.labels[i], 295 | options: { 296 | fill: i > whiteIdx ? '#ffffff' : '#000000', 297 | fontSize: blocHeight * 0.8, 298 | fontWeight: 'bold', 299 | fontFamily: "'Arial Narrow', sans-serif", 300 | textAnchor: 'end' 301 | } 302 | })); 303 | svg.appendChild(self.getText( 304 | { 305 | x: x + self.pad, 306 | y: y + blocHeight - ((blocHeight * 0.6) / 2), 307 | text: self.values[i], 308 | options: { 309 | fill: i > whiteIdx ? '#ffffff' : '#000000', 310 | fontSize: blocHeight * 0.6, 311 | fontFamily: "'Arial Narrow', sans-serif", 312 | textAnchor: 'start' 313 | } 314 | })); 315 | } 316 | 317 | self.container.appendChild(svg); 318 | }; 319 | 320 | self.createSVG(); 321 | }; 322 | 323 | function DPE(options) { 324 | 325 | options.valuesRange = [ 326 | { min: null, max: 50, color: '#319834', textColor: '#000000', label: 'A' }, 327 | { min: 51, max: 90, color: '#33cc31', textColor: '#000000', label: 'B' }, 328 | { min: 91, max: 150, color: '#cbfc34', textColor: '#000000', label: 'C' }, 329 | { min: 151, max: 230, color: '#fbfe06', textColor: '#000000', label: 'D' }, 330 | { min: 231, max: 330, color: '#fbcc05', textColor: '#000000', label: 'E' }, 331 | { min: 331, max: 450, color: '#fc9935', textColor: '#000000', label: 'F' }, 332 | { min: 451, max: null, color: '#fc0205', textColor: '#ffffff', label: 'G' } 333 | ]; 334 | 335 | options.shape = "sharp"; 336 | 337 | return new Diag(options); 338 | }; 339 | 340 | function GES(options) { 341 | 342 | options.valuesRange = [ 343 | { min: null, max: 5, color: '#f2eff4', textColor: '#000000', label: 'A' }, 344 | { min: 6, max: 10, color: '#dfc1f7', textColor: '#000000', label: 'B' }, 345 | { min: 11, max: 20, color: '#d6aaf4', textColor: '#000000', label: 'C' }, 346 | { min: 21, max: 35, color: '#cc93f4', textColor: '#000000', label: 'D' }, 347 | { min: 36, max: 55, color: '#bb72f3', textColor: '#ffffff', label: 'E' }, 348 | { min: 56, max: 80, color: '#a94cee', textColor: '#ffffff', label: 'F' }, 349 | { min: 81, max: null, color: '#8b1ae1', textColor: '#ffffff', label: 'G' } 350 | ]; 351 | 352 | options.shape = "flat"; 353 | 354 | return new Diag(options); 355 | }; 356 | 357 | return { 358 | dpe: DPE, 359 | ges: GES 360 | }; 361 | 362 | }; 363 | --------------------------------------------------------------------------------