1var sGraf = function ( sGraf ) { 2 3 var grafficId = 0, 4 is_downed = false, 5 kX = [], kY = [], grafficsData = [], 6 smallView = false; 7 skinId = 0, 8 skin = {}, 9 mode = 'svg'; 10 // previousDay = {}; 11 12 sGraf.initSkin = function( id , getDefault ){ 13 14 skin.enableMouseMoveHandler = true; 15 skin.autoHeight = false; 16 17 skin.colors = [ '#3295FF' , '#ff4165' , '#08d34e', '#f6a500', '#ba00f6', '#7c6a61', '#78b6a2', '#75575c' , '#1f9e2b']; 18 skin.colorsA = [ 'rgba(0,162,255,.1)' , 'rgba(255,0,123,.1)' , 'rgba(0,255,84,.17)' , 'rgba(255,169,33,.11)' , 'rgba(238,21,252,.13)', 'rgba(124,104,125,.13)', 'rgba(53,195,150,.5)', 'rgba(140,52,52,.3)' , 'rgba(2,134,27,.4)' ]; 19 20 skin.position = { 21 graffic : { right: 0 , top : 0 }, 22 bottomLegend : { bottom : 0 , right : 0}, 23 leftLegend : { left: 0 , top: 0} 24 } 25 26 skin.gridColor = '#dcebf6'; 27 skin.legendColor = '#bcc9d2'; 28 skin.legendWeekendsColor = '#d77e80'; 29 skin.gridWidth = 1; 30 skin.grafficWidth = 0; 31 skin.legendFontSize = 12; 32 33 skin.shortValues = false; 34 35 skin.valueBoxType = 1; 36 skin.showLegends = true; 37 skin.showVerticalGridLines = true; 38 skin.showHorisontalGridLines = true; 39 skin.showCircles = true; 40 skin.showTitles = true; 41 skin.leftLegendWidth = 40; 42 skin.bottomLegendHeight = 40; 43 skin.animateCircles = false; 44 skin.animateGraphLine = false; 45 skin.animateGridLines = false; 46 skin.canvasRightMargin = false; 47 48 skin.summary = false ; 49 50 51 if ( id == 1 ){ 52 53 skin.enableMouseMoveHandler = false; 54 55 skin.colors = [ '#9faab7' , '#dadee4']; 56 skin.colorsA = [ 'rgba(108, 119, 132, .1)' , 'rgba(255, 255, 255, .9)']; 57 58 skin.position = { 59 graffic : { left: 0 , top : 0 }, 60 bottomLegend : {bottom : 0 , left : 0}, 61 leftLegend : {left: 0 , top: 0} 62 } 63 64 skin.gridColor = '#bcc9d2'; 65 skin.grafficWidth = 3; 66 skin.legendFontSize = 9; 67 68 skin.shortValues = true; 69 70 skin.showLegends = false; 71 skin.showVerticalGridLines = false; 72 skin.showHorisontalGridLines = false; 73 skin.leftLegendWidth = 10; 74 skin.bottomLegendHeight = 0; 75 skin.animateCircles = true; 76 skin.animateGraphLine = true; 77 skin.animateGridLines = true; 78 skin.gridLinesAnimateSpeed = '1s'; 79 skin.graphLinesAnimateSpeed = '1.5s'; 80 81 skin.showTitles = false; 82 83 skin.canvasRightMargin = 80; 84 85 skin.summary = { 86 87 curDay : { 88 fontSize : '18px', 89 color : '#9da2a8', 90 fontWeight : '500', 91 position : 'relative' 92 }, 93 conversion : { 94 fontSize : '12px', 95 progressiveColor : '#7acd9b', 96 regressiveColor : '#dda6a6', 97 fontWeight : 'normal' 98 }, 99 wrap : { 100 textAlign : 'right', 101 position : 'absolute', 102 right : 0, 103 top : 0 104 } 105 106 }; 107 108 } else if ( id == 2 ){ 109 110 skin.autoHeight = true; 111 112 skin.showVerticalGridLines = true; 113 skin.showHorisontalGridLines = false; 114 115 skin.leftLegendWidth = 0; 116 skin.bottomLegendHeight = 0; 117 skin.showLegends = false; 118 skin.showCircles = false; 119 skin.showTitles = false; 120 121 skin.valueBoxType = 2; 122 123 } 124 125 }; 126 127 sGraf.make = function ( params ) { 128 129 skinId = !isNaN(params.skinId) ? params.skinId : 0; 130 131 sGraf.initSkin( skinId ); 132 133 if (params.mode == 'canvas') mode = 'canvas'; 134 135 if ( !params.wrapper ){ console.warn('Wrong or missed wrapper'); return; } 136 if ( !params.data || !params.titles ){ sGraf.showErrorMessage ( params.wrapper , 'Error with graph data' ); return; } 137 138 // previousDay = params.prevDay || {}; 139 140 var defaultSize = { 141 width : 320, 142 height : 150 143 }; 144 145 146 var canvasHeight = params.wrapper.offsetHeight > 0 ? params.wrapper.offsetHeight : defaultSize.height, 147 canvasWidth = canvasHeight == defaultSize.height ? defaultSize.width - skin.leftLegendWidth : params.wrapper.offsetWidth - skin.leftLegendWidth; 148 149 if (skin.canvasRightMargin) { 150 canvasWidth -= skin.canvasRightMargin; 151 }; 152 153 if ( skin.autoHeight && canvasHeight < 150 ){ 154 canvasWidth = 350 / 150 * canvasHeight; 155 } 156 157 params.wrapper.style.width = canvasWidth + skin.leftLegendWidth + 'px'; 158 params.wrapper.style.height = canvasHeight + skin.bottomLegendHeight + 'px'; 159 160 161 if ( mode == 'canvas' ){ 162 163 var leftLegendCanvas = sGraf.createElement( 'canvas' , { id : 'left_legend_' + grafficId, 'width' : skin.left
163LegendWidth , 'height' : canvasHeight } ), 164 grafficCanvas = sGraf.createElement( 'canvas' , { id : 'graffic_' + grafficId, 'width' : canvasWidth , 'height' : canvasHeight } ), 165 bottomLegendCanvas = sGraf.createElement( 'canvas' , { id : 'bottom_legend_' + grafficId, 'width' : canvasWidth + skin.leftLegendWidth, 'height' : skin.bottomLegendHeight } ); 166 167 168 params.wrapper.appendChild( leftLegendCanvas ); 169 params.wrapper.appendChild( grafficCanvas ); 170 params.wrapper.appendChild( bottomLegendCanvas ); 171 172 sGraf.redraw( grafficCanvas , params.data , params.titles , grafficId ); 173 174 175 } else if ( mode == 'svg' ){ 176 177 var grafficSVG = sGraf.createElement( 'svg' , { id : 'graffic_' + grafficId } , true), 178 leftLegendSVG = sGraf.createElement( 'svg' , { id : 'left_legend_' + grafficId } , true ), 179 bottomLegendSVG = sGraf.createElement( 'svg' , { id : 'bottom_legend_' + grafficId } , true ); 180 181 182 grafficSVG.style.width = canvasWidth + 'px'; 183 grafficSVG.style.height = canvasHeight + 'px'; 184 grafficSVG.style.position = 'absolute'; 185 186 if ( skin.leftLegendWidth && !isNaN(skin.position.graffic.left) ) { 187 skin.position.graffic.left += skin.leftLegendWidth; 188 skin.position.graffic.left += 'px'; 189 }; 190 191 sGraf.setStyles( grafficSVG , skin.position.graffic ); 192 193 194 bottomLegendSVG.style.height = skin.bottomLegendHeight + 'px'; 195 bottomLegendSVG.style.width = canvasWidth + skin.leftLegendWidth + 'px'; 196 bottomLegendSVG.style.position = 'absolute'; 197 sGraf.setStyles( bottomLegendSVG , skin.position.bottomLegend ); 198 199 // leftLegendSVG.style.width = skin.leftLegendWidth + 'px'; 200 leftLegendSVG.style.height = canvasHeight + 'px'; 201 leftLegendSVG.style.position = 'absolute'; 202 sGraf.setStyles( leftLegendSVG , skin.position.leftLegend ); 203 204 params.wrapper.style.position = 'relative'; 205 206 if (skin.canvasRightMargin) { 207 params.wrapper.style.width = parseInt(params.wrapper.style.width, 10) + skin.canvasRightMargin + 'px'; 208 }; 209 210 params.wrapper.innerHTML = ''; 211 params.wrapper.appendChild( grafficSVG ); 212 params.wrapper.appendChild( bottomLegendSVG ); 213 params.wrapper.appendChild( leftLegendSVG ); 214 215 params.wrapper.dataset.id = grafficId; 216 217 sGraf.processing({ 218 219 svgTag : grafficSVG, 220 data : params.data, 221 titles : params.titles, 222 grafficId : grafficId, 223 canvasWrap : params.wrapper 224 225 }); 226 227 228 } 229 230 231 grafficId++; 232 233 // grafficCanvas.addEventListener( 'mousemove' , sGraf.mMove , false ); 234 // grafficCanvas.addEventListener( 'click' , sGraf.processClick , false ); 235 // grafficCanvas.addEventListener( 'mousedown' , sGraf.mDown , false ); 236 // grafficCanvas.addEventListener( 'mouseup' , sGraf.mUp , false ); 237 238 239 240 }; 241 242 sGraf.showErrorMessage = function ( wrapper , message ) { 243 244 var error_block = sGraf.createElement('div' , { class : 'graffic_error' } ); 245 246 error_block.style.background = '#F9EBEB'; 247 error_block.style.padding = '15px'; 248 error_block.style.color = '#A76F6F'; 249 error_block.innerHTML = message; 250 251 wrapper.appendChild(error_block); 252 253 254 }; 255 256 sGraf.getMinMaxValues = function ( data ){ 257 258 var aLength = data.length, 259 a2Length = 0, 260 curData = [], 261 i = 0, 262 j = 0, 263 max = -99999, 264 min = 99999, 265 maxDate = -99999; 266 267 268 for (i; i < aLength; i++) { 269 270 if ( data[i]['date'] > maxDate ) maxDate = data[i]['date']; 271 272 curData = data[i]['counts']; 273 a2Length = curData.length; 274 275 for ( j = 0 ; j < a2Length; j++) { 276 277 if ( curData[j] > max ) max = curData[j]; 278 if ( curData[j] < min ) min = curData[j]; 279 280 } 281 282 } 283 284 return { max : max , min : min , maxDate : maxDate }; 285 286 }; 287 288 sGraf.localeMonth = function ( month ) { 289 290 291 if ( isNaN(month) ) return false; 292 293 var lang = navigator.language == 'ru' ? 0 : 1, 294 map = { 295 ru : ['Янв','Фев','ÐаÑ','ÐпÑ','ÐаÑ','ÐÑн','ÐÑл','Ðвг','Сен','ÐкÑ','ÐоÑ','Ðек'], 296 en : ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] 297 }; 298 299 return lang ? map.en[month] : map.ru[month]; 300 301 }; 302 303 sGraf.drawGrid = function( params ){ 304 305 params.grafficId = !isNaN(params.grafficId) ? params.grafficId : false;
306 params.canvasWidth = params.canvasWidth || 400; 307 params.canvasHeight = params.canvasHeight || 150; 308 params.kX = params.kX || 1; 309 params.kY = params.kY || 1; 310 params.titles = params.titles || []; 311 params.bottomLegendData = params.bottomLegendData || {}; 312 params.minMaxValues = params.minMaxValues || {}; 313 314 315 var margin = 10, 316 prevX = margin, 317 prevY = 0, 318 legendStepY = 200, 319 legendStepX = 200, 320 leftLegendCanvas, bottomLegendCanvas, leftLegendWrap, bottomLegendWrap, grafficWrap; 321 322 323 if ( mode == 'canvas' ){ 324 325 leftLegendCanvas = document.getElementById('left_legend_' + params.grafficId); 326 bottomLegendCanvas = document.getElementById('bottom_legend_' + params.grafficId); 327 328 // contexts 329 leftLegendWrap = leftLegendCanvas.getContext('2d'); 330 bottomLegendWrap = bottomLegendCanvas.getContext('2d'); 331 332 bottomLegendWrap.clearRect(0, 0, 10000, 10000); 333 leftLegendWrap.clearRect(0, 0, 10000, 10000); 334 335 grafficWrap = params.context; 336 337 } else if ( mode == 'svg' ){ 338 339 bottomLegendWrap = document.getElementById('bottom_legend_' + params.grafficId); 340 leftLegendWrap = document.getElementById('left_legend_' + params.grafficId); 341 grafficWrap = params.svgTag; 342 343 344 } 345 346 347 348 if ( params.minMaxValues['max'] < 10 ) { 349 legendStepY = 1; 350 } else if ( params.minMaxValues['max'] < 100 ){ 351 legendStepY = 10; 352 } else if ( params.minMaxValues['max'] < 1000 ){ 353 legendStepY = 100; 354 } else if ( params.minMaxValues['max'] < 10000 ){ 355 legendStepY = 1000; 356 } else if ( params.minMaxValues['max'] < 50000 ){ 357 legendStepY = 5000; 358 } else if ( params.minMaxValues['max'] < 100000 ){ 359 legendStepY = 10000; 360 } else if ( params.minMaxValues['max'] < 1000000 ){ 361 legendStepY = 100000; 362 } 363 364 if ( params.minMaxValues['maxDate'] < 10 ) { 365 legendStepX = 1; 366 } else if ( params.minMaxValues['maxDate'] < 50 ){ 367 legendStepX = 5; 368 } else if ( params.minMaxValues['maxDate'] < 100 ){ 369 legendStepX = 10; 370 } else if ( params.minMaxValues['maxDate'] < 1000 ){ 371 legendStepX = 100; 372 } 373 374 // legendStepX = Math.ceil(params.minMaxValues['max'] / 10); 375 // legendStepY = Math.ceil(params.minMaxValues['maxDate'] / 10); 376 377 var xLinesCount = params.canvasWidth / ( legendStepX * params.kX ) >> 0, 378 yLinesCount = params.kY != 1 ? params.canvasHeight / ( legendStepY * params.kY ) >> 0 : 0, 379 legendDetermineX = legendStepX, 380 legendDetermineY = legendStepY; 381 382 if ( isNaN(xLinesCount) ) xLinesCount = 0; 383 if ( isNaN(yLinesCount) ) xLinesCount = 0; 384 385 386 if ( skin.showHorisontalGridLines ){ 387 // axis X 388 sGraf.draw.line( grafficWrap, margin , params.canvasHeight , params.canvasWidth + margin, params.canvasHeight , skin.gridColor , skin.gridWidth); 389 } 390 391 // Drawing vertical lines 392 for (var i = xLinesCount; i >= 0 ; i--) { 393 394 var x = i === xLinesCount ? margin : prevX + ( legendStepX * params.kX ) ; 395 396 if ( skin.showVerticalGridLines ){ 397 sGraf.draw.line( grafficWrap , x , margin , x, params.canvasHeight , skin.gridColor , skin.gridWidth); 398 } 399 400 //Drawing Bottom Legend - DAYS 401 if ( skin.showLegends ){ 402 sGraf.drawBottomLegendText( x , i , bottomLegendWrap , legendDetermineX , xLinesCount); 403 } 404 405 prevX = x; 406 407 } 408 409 // Drawing horisontal lines 410 for (var j = 0; j <= yLinesCount; j++) { 411 412 var y = params.canvasHeight - (prevY + ( legendStepY * params.kY ) ); 413 414 if ( skin.showHorisontalGridLines ){ 415 if ( j < yLinesCount ) { 416 sGraf.draw.line( grafficWrap , margin , y, params.canvasWidth + margin , y , skin.gridColor , skin.gridWidth ) 417 } 418 } 419 420 if ( skin.showLegends ){ 421 if ( legendDetermineY * j % 1 === 0 ){ 422 sGraf.draw.text( leftLegendWrap , legendDetermineY * j, 40 , params.canvasHeight - prevY + 7 , skin.legendColor , skin.legendFontSize , 'end' ) 423 } 424 } 425 426 prevY += legendStepY * params.kY; 427 if ( yLinesCount === 0 ) break; 428 } 429 430 431 if ( skin.showTitles ){ 432 433 sGraf.drawGrafficLegendTitles( bottomLegendWrap , params.titles ); 434 435 } 436 437 438 }; 439 440 sGraf.drawBottomLegendText = function ( x , i , wrap , legendDetermineX , xLinesCount ){ 441 442 if ( legendDetermineX * i % 1 === 0 ){ 443 if ( xLinesCount < 10 || i % Math.floor( xLinesCount / 10 ) === 0 ){ 444 445 var now = new Date(),
446 text_x = skin.leftLegendWidth + x , 447 text_y = 10, 448 text = '', 449 color = skin.legendColor; 450 451 now.setDate(now.getDate() - legendDetermineX*i); 452 453 text = now.getDate() + ' ' + sGraf.localeMonth( now.getMonth() ); 454 455 /** Color for Weekends Days */ 456 if (now.getDay() == 0 || now.getDay() == 6 ) { 457 color = skin.legendWeekendsColor; 458 }; 459 460 461 sGraf.draw.text( wrap, text , text_x, text_y , color , skin.legendFontSize , i === 0 ? 'end' : 'middle'); 462 } 463 464 } 465 466 }; 467 468 sGraf.draw = { 469 470 line : function ( wrap , fromX , fromY, toX, toY , color , size){ 471 472 size = size || 1; 473 474 if ( mode == 'canvas' ){ 475 476 wrap.beginPath(); 477 wrap.strokeStyle = color; 478 wrap.moveTo( fromX, fromY ); 479 wrap.lineWidth = size; 480 wrap.lineTo( toX , toY ); 481 wrap.stroke(); 482 483 } else if ( mode == 'svg' ){ 484 485 var curPath = sGraf.createElement('path', { d: 'M' + fromX + ' ' + fromY + ' L' + toX + ' ' + toY + ' Z', stroke : color , 'stroke-dasharray' : '5,5' , 'stroke-linecap' : 'round', 'stroke-width' : size } , true); 486 487 wrap.appendChild(curPath); 488 489 if (skin.animateGridLines) { 490 sGraf.animateLine( curPath , skin.gridLinesAnimateSpeed ); 491 }; 492 493 return curPath; 494 495 } 496 497 }, 498 499 text : function ( wrap, text , x , y , color , size , textAnchor) { 500 501 if ( mode == 'canvas' ) { 502 503 var textAlign; 504 505 switch (textAnchor){ 506 default : 507 case 'start' : textAlign = 'left'; break; 508 case 'end' : textAlign = 'right'; break; 509 case 'middle' : textAlign = 'center'; break; 510 }; 511 512 wrap.fillStyle = color; 513 wrap.textAlign = textAlign; 514 wrap.font = size + 'pt Tahoma, Geneva'; 515 wrap.fillText( text , x, y ); 516 517 } else if ( mode == 'svg' ){ 518 519 // if ( y < 10 ) y = 10; 520 521 textAnchor = textAnchor || 'start'; 522 523 var curText = sGraf.createElement('text', { x: x , y: y, fill : color, 'text-anchor' : textAnchor , 'dominant-baseline' : 'use-script' } , true ); 524 525 curText.style.fontSize = size + 'px'; 526 527 528 wrap.appendChild(curText); 529 530 var textNode = document.createTextNode(text); 531 curText.appendChild(textNode); 532 533 return curText; 534 535 } 536 } 537 }; 538 539 sGraf.processing = function ( params ){ 540 541 params.grafficId = !isNaN(params.grafficId) ? params.grafficId : false; 542 543 var canvasMargin = 10, 544 dataLength = params.data.length, 545 i = 0, 546 j = 0, 547 graffics = [], 548 canvasWidth = 0, 549 canvasHeight = 0; 550 551 var MinMax = sGraf.getMinMaxValues( params.data ), 552 maxValue = MinMax['max'], 553 minValue = MinMax['min'], 554 maxDate = MinMax['maxDate']; 555 556 557 for ( i = 0 ; i < params.data[0]['counts'].length ; i++) { // [ [{ date: 0 , count : 101 } , { date : 1 , count : 50 } , ... ] , [ ... ] ] 558 559 var graffic_data = []; 560 561 for ( j = 0 ; j < dataLength ; j++) { 562 563 graffic_data.push({ date : params.data[j]['date'], 'count' : params.data[j]['counts'][i] }); 564 565 } 566 567 graffics.push(graffic_data); 568 569 } 570 571 572 573 if ( mode == 'canvas' ) { 574 575 canvasWidth = params.canvas.width - canvasMargin * 2; 576 canvasHeight = params.canvas.height - canvasMargin * 2; 577 578 } else if ( mode == 'svg' ){ 579 580 canvasWidth = parseInt(params.svgTag.style.width , 10 ) - canvasMargin * 2; 581 canvasHeight = parseInt(params.svgTag.style.height , 10 ) - canvasMargin * 2; 582 583 } 584 585 var kY = maxValue !== 0 ? canvasHeight / maxValue : 1, 586 kX = canvasWidth / ( params.data[dataLength-1]['date'] - params.data[0]['date'] ); 587 588 589 // if ( skin.showGrid) { 590 591 sGraf.drawGrid({ 592 593 context : params.context, 594 svgTag : params.svgTag, 595 grafficId : params.grafficId, 596 canvasWidth : canvasWidth, 597 canvasHeight : canvasHeight + canvasMargin, 598 kX : kX, 599 kY : kY, 600 titles : params.titles, 601 bottomLegendData : graffics, 602 minMaxValues : MinMax, 603 canvasWrap : params.canvasWrap 604 605 }); 606 607 // }; 608 609 if ( mode == 'canvas' ){ 610 611 sGraf.drawCanvasGraffic({ 612 613 canvas : params.canvas, 614 data : graffics, 615 canvasMargin : canvasMargin, 616 kX : kX, 617 kY : kY 618 619 }); 620 621 } else if ( mode == 'svg' ){ 622 623 sGraf.drawSVGGraffic({ 624 625 svgTag : params.svgTag, 626 data : graffics, 627 canvasMargin : canvasMargin, 628 kX : kX, 629 kY : kY, 630 grafficId : params.grafficId, 631 canvasWrap : params.canvasWrap, 632 MinMax : MinMax 633 634 }); 635 636 if ( skin.summary ) { 637 638 sGraf.drawSummary({ 639 wrap : params.canvasWrap, 640 data : graffics, 641 grafficId : params.grafficId 642 }); 643 644 }; 645 646 647 648 // sGraf.appendBottomLegend({ 649 // titles : params.titles, 650 // grafficId : params.grafficId 651 // }); 652 653 } 654 655 656 657 }; 658 659 sGraf.drawSummary = function ( params ){ 660 661 var graffics = params.data, 662 curDayValue = 0, 663 prevDayValue = 0; 664 665 var appendSummaryBlock = function ( wrap , grafficId, curDay, prevDay ){ 666 667 var summaryWrap = sGraf.createElement('div', {id : 'graph_' + grafficId + '_summary'}, false), 668 curDayValueWrap = sGraf.createElement('div', {class : 'curDay'}, false), 669 conversionWrap = sGraf.createElement('div', {class : 'conversion'}, false); 670 671 var makeProgressTrianle = function ( wrap , conversion ){ 672 673 var svg = sGraf.createElement( 'svg' , {} , true), 674 path = conversion > 0 ? 'M 0 5 L5 0 L10 5 Z' : 'M 0 0 L5 5 L10 0 Z', 675 color = conversion > 0 ? skin.summary.conversion.progressiveColor : skin.summary.conversion.regressiveColor, 676 triangle = sGraf.createElement( 'path' , { 677 fill : color, 678 d : path 679 } , true); 680 681 svg.style.position = 'absolute'; 682 svg.style.left = '10px'; 683 svg.style.top = '10px'; 684 685 svg.appendChild(triangle); 686 wrap.appendChild(svg); 687 688 }; 689 690 691 692 sGraf.setStyles(curDayValueWrap , skin.summary.curDay ); 693 sGraf.setStyles(conversionWrap , skin.summary.conversion ); 694 sGraf.setStyles(summaryWrap , skin.summary.wrap ); 695 696 curDayValueWrap.innerHTML = curDay > 2000 ? sGraf.makeShortVal(curDay) : curDay; 697 698 699 700 var conversion = curDay - prevDay, 701 // conversionPercentage = Math.floor((prevDay / 100) * (conversion)); 702 conversionPercentage = (conversion < 0 ? -1 : 1) * (prevDay ? Math.abs(Math.floor(100 - (100 * curDay) / prevDay)) : 100); 703 704 705 706 if ( conversion > 0 ){ 707 conversionWrap.innerHTML = '+' + sGraf.makeShortVal(conversion) + ' (' + sGraf.makeShortVal(conversionPercentage) + '%)'; 708 conversionWrap.style.color = skin.summary.conversion.progressiveColor; 709 } else{ 710 conversionWrap.innerHTML = sGraf.makeShortVal(conversion) + ' (' + sGraf.makeShortVal(conversionPercentage) + '%)'; 711 conversionWrap.style.color = skin.summary.conversion.regressiveColor; 712 } 713 714 makeProgressTrianle(summaryWrap , conversion ); 715 716 717 summaryWrap.appendChild(curDayValueWrap); 718 summaryWrap.appendChild(conversionWrap); 719 720 wrap.appendChild(summaryWrap); 721 722 }; 723 724 for (var i = 0 ; i < graffics.length ; i++) { 725 726 var graffic = graffics[i], 727 days = graffic.length; 728 729 curDayValue = graffic[days - 1]['count']; 730 prevDayValue = graffic[days - 2]['count']; 731 732 appendSummaryBlock( params.wrap , params.grafficId, curDayValue , prevDayValue ); 733 734 break; 735 736 } 737 738 }; 739 740 sGraf.makeShortVal = function (num){ 741 742 if (Math.abs(num) >= 1000000000) { 743 return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G'; 744 } 745 if (Math.abs(num) >= 1000000) { 746 return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M'; 747 } 748 if (Math.abs(num) >= 1000) { 749 return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; 750 } 751 752 return num.toFixed(1).replace(/\.0$/, ''); 753 754 }; 755 756 757 sGraf.setStyles = function ( obj , styles ){ 758 759 for(var name in styles) { 760 761 obj.style[name] = styles[name] 762 763 } 764 }; 765 766 sGraf.appendBottomLegend = function (params) { 767 768 var graffic_block = document.getElementById('g' + params.grafficId); 769 770 setTimeout( function () { 771 772 if ( !graffic_block ) return; 773 774 for ( titles_i = 0; titles_i < params.titles.length ; titles_i++ ){ 775 776 var graffic_title = sGraf.createElement('span', { id : 'g' + params.grafficId + '_title' + titles_i } ); 777 778 graffic_title.innerHTML = params.titles[titles_i]; 779 graffic_title.style.color = skin.colors[titles_i]; 780 781 graffic_block.appendChild( graffic_title); 782 783 } 784 785 }, 300); 786 }; 787 788 sGraf.drawCanvasGraffic = function ( params ){ 789 790 params = { 791 792 data : params.data ? params.data : [], 793 canvas : params.canvas ? params.canvas : false, 794 kX : params.kX ? params.kX : 1, 795 kY : params.kY ? params.kY : 1, 796 canvasMargin : params.canvasMargin ? params.canvasMargin : 30 797 798 }; 799 800 var context = params.canvas.getContext('2d'), 801 canvasWidth = params.canvas.width - params.canvasMargin * 2, 802 canvasHeight = params.canvas.height - params.canvasMargin * 2, 803 graffics = params.data, 804 prevX = 0, 805 prevY = 0; 806 807 808 context.save(); 809 810 for ( i = 0 ; i < graffics.length ; i++) { 811 812 prevX = 0; 813 prevY = 0; 814 815 for ( j = 0 ; j < graffics[i].length ; j++) { 816 817 var x = parseInt( graffics[i][j]['date'] , 10 ) * params.kX + params.canvasMargin, 818 y = canvasHeight - parseInt( graffics[i][j]['count'] , 10 ) * params.kY + params.canvasMargin; 819 820 // draw line 821 context.beginPath(); 822 823 if ( j !== 0) context.moveTo( prevX , prevY ); 824 context.lineWidth = 1; 825 // context.strokeStyle = skin.colors[i]; 826 context.lineTo( x , y ); 827 context.lineJoin = 'round'; 828 829 context.stroke(); 830 831 832 if ( graffics[i].length < 50 ){ 833 834 context.textAlign = 'right'; 835 836 context.fillStyle = skin.colors[i]; 837 context.fillText( graffics[i][j]['count'] , x + 8, y - 3 ); 838 839 //draw cicrcle 840 841 context.beginPath(); 842 context.fillStyle = skin.colors[i]; 843 context.lineWidth = 2; 844 context.strokeStyle = skin.colors[i]; 845 context.arc( x , y , 2 , 0 , 2 * Math.PI , false ); 846 context.stroke(); 847 context.fill(); 848 849 } 850 851 prevX = x; 852 prevY = y; 853 854 } 855 856 } 857
858 context.restore(); 859 860 }; 861 862 sGraf.drawGrafficLegendTitles = function ( wrap , titles ){ 863 864 var lineWidth = 15, title_i; 865 866 if ( mode == 'canvas' ){ 867 868 for ( titles_i = 0; titles_i < titles.length ; titles_i++ ){ 869 870 x = 30 + ( lineWidth + 20 + 20 ) * titles_i; 871 y = 36; 872 873 context.beginPath(); 874 context.moveTo( x , y ); 875 context.lineTo( x + lineWidth , y ); 876 context.strokeStyle = skin.colors[titles_i]; 877 context.fillStyle = skin.colors[titles_i]; 878 context.lineWidth = 2; 879 context.textAlign = 'left'; 880 context.fillText( titles[titles_i] , x + lineWidth + 10 , y + 2 ); 881 context.stroke(); 882 883 884 } 885 886 } else { 887 888 for ( titles_i = 0; titles_i < titles.length ; titles_i++ ){ 889 890 var titles_x = 30 + ( lineWidth + 20 + 90 ) * titles_i, 891 titles_y = 36; 892 893 var line = sGraf.draw.line(wrap , titles_x , titles_y , titles_x + lineWidth , titles_y , skin.colors[titles_i] , 4 ), 894 lineText = document.createTextNode(titles[titles_i]), 895 lineTextTag = sGraf.createElement('text', { x: (titles_x + lineWidth) + 10 , y: titles_y + 3, fill : skin.colors[titles_i] } , true ); 896 897 wrap.appendChild(line); 898 wrap.appendChild(lineTextTag); 899 lineTextTag.appendChild(lineText); 900 901 } 902 903 } 904 905 }; 906 907 sGraf.redraw = function ( canvas , data, titles, grafficId , infoX ){ 908 909 var ctx = canvas.getContext('2d'); 910 911 ctx.clearRect(0, 0, canvas.width, canvas.height); 912 913 sGraf.processing({ 914 canvas : canvas, 915 context : ctx, 916 data : data, 917 titles : titles, 918 grafficId : grafficId, 919 infoX : infoX 920 }); 921 922 }; 923 924 sGraf.makeSVG = function( canvasWrap , data , titles ){ 925 926 }; 927 928 sGraf.drawSVGGraffic = function( params ){ 929 930 params.canvasMargin = params.canvasMargin || 0; 931 params.kX = params.kX || 1.5; 932 params.kY = params.kY || 1.5; 933 params.grafficId = !isNaN(params.grafficId) ? params.grafficId : false; 934 935 var dataLength = params.data.length, 936 canvasWidth = params.svgTag.offsetWidth - params.canvasMargin * 2, 937 canvasHeight = parseInt( params.svgTag.style.height , 10 ) - params.canvasMargin * 2, 938 i = 0, 939 j = 0, 940 prevX = 0, 941 prevY = 0, 942 graffics = params.data; 943 944 945 grafficsData[params.grafficId] = []; 946 947 948 for ( i = 0 ; i < graffics.length ; i++) { 949 950 prevX = 0; 951 prevY = canvasHeight + params.canvasMargin; 952 953 var points = '', 954 path = ''; 955 956 grafficsData[params.grafficId].push(graffics[i]); 957 958 959 for ( j = 0 ; j < graffics[i].length ; j++) { 960 961 962 var x = Math.round(parseInt( graffics[i][j]['date'] , 10 ) * params.kX + params.canvasMargin), 963 y = Math.round(canvasHeight - parseInt( graffics[i][j]['count'] , 10 ) * params.kY + params.canvasMargin); 964 965 966 x = !isNaN(x) ? x : 0; 967 y = !isNaN(y) ? y : canvasHeight + params.canvasMargin; 968 969 points += x + ',' + y + ' '; 970 971 if ( j === 0 ){ 972 path += 'M ' + x + ' ' + y; 973 } else { 974 975 path += ' L' + x + ' ' + y ; 976 977 } 978 979 // if (j !== 0) { 980 981 // var line = sGraf.createElement('line', {x1: prevX, y1: prevY, x2 : x, y2: y} , true); 982 // line.style.stroke = skin.colors[i]; 983 // line.style.strokeWidth = 2; 984 985 // params.svgTag.appendChild(line) 986 987 // }; 988 989 990 991 if ( graffics[i][j]['count'] > 0 && graffics[i][j]['count'] == params.MinMax['max']){ 992 993 var text_x = j > 3 ? x - 20 : x + 20, 994 text_str = skin.shortValues ? sGraf.makeShortVal(graffics[i][j]['count']) : graffics[i][j]['count']; 995 996 var curText = sGraf.draw.text( params.svgTag , text_str, text_x , ( y > 13 ? y - 5 : 8) , skin.colors[i] , 11, 'middle'); 997 998 } 999 1000 // DRAWING CIRCLES 1001 if ( skin.showCircles ){ 1002 1003 if ( skin.animateCircles ) { 1004 1005 sGraf.appendCircle( params.svgTag , x , y , 1 , skin.colors[i] ); 1006 1007 } else { 1008 1009 var cicrcle = sGraf.createElement('circle', { cx : x, cy : y , r : 2, fill : skin.colors[i] } , true); 1010 params.svgTag.appendChild(cicrcle); 1011 1012 }; 1013 1014 } 1015 1016 prevX = x; 1017 prevY = y; 1018 1019 } 1020 1021 // points += prevX + ',' + (canvasHeight + params.canvasMargin) + ' '; 1022 // points += params.canvasMargin + ',' + (canvasHeight + params.canvasMargin); 1023 1024 // var curLine = sGraf.createElement('polygon', { points: points } , true); 1025 1026 // curLine.style.stroke = skin.colors[i]; 1027 // curLine.style.strokeWidth = 0.5; 1028 // curLine.style.fill = skin.colorsA[i]; 1029 1030 // params.svgTag.appendChild(curLine); 1031
1032 var graffic_fill_color = !smallView ? skin.colorsA[i] : skin.colors[i], 1033 graffic_opacity = !smallView ? 1 : 0.35, 1034 curPath; 1035 1036 if ( skin.animateGraphLine ) { 1037 1038 graffic_fill_color = 'transparent'; 1039 curPath = sGraf.createElement('path', { d: path , 'stroke-width' : '3', stroke : skin.colors[i] , opacity : graffic_opacity, fill : graffic_fill_color , 'id' : params.grafficId } , true); 1040 1041 } else { 1042 1043 path += ' L' + prevX + ' ' + (canvasHeight + params.canvasMargin); 1044 path += ' L' + params.canvasMargin + ' ' + (canvasHeight + params.canvasMargin); 1045 1046 curPath = sGraf.createElement('path', { d: path + ' Z', 'stroke-width' : '0', stroke : skin.colors[i] , opacity : graffic_opacity, fill : graffic_fill_color , 'id' : params.grafficId } , true); 1047 1048 } 1049 1050 params.svgTag.appendChild(curPath); 1051 1052 if (skin.animateGraphLine) { 1053 sGraf.animateLine( curPath , skin.graphLinesAnimateSpeed ); 1054 }; 1055 1056 1057 1058 1059 if ( skin.valueBoxType == 1 ){ 1060 1061 sGraf.createValueBox({ 1062 parent : params.svgTag, 1063 x : -30, 1064 y : canvasHeight, 1065 grafficId : grafficId, 1066 grafficNumber : i 1067 }); 1068 1069 } 1070 1071 1072 1073 1074 1075 } 1076 1077 if ( skin.valueBoxType == 2 ){ 1078 1079 sGraf.createValueBox({ 1080 parent : params.svgTag, 1081 x : params.canvasWrap.offsetWidth, 1082 y : canvasHeight, 1083 grafficId : grafficId, 1084 grafficNumber : i 1085 }); 1086 1087 params.canvasWrap.addEventListener( 'mouseover' , sGraf.grafficHover , false ); 1088 params.canvasWrap.addEventListener( 'mouseout' , sGraf.grafficBlur , false ); 1089 1090 } 1091 1092 if ( skin.enableMouseMoveHandler ) { 1093 1094 params.canvasWrap.addEventListener( 'mousemove' , sGraf.grafficMouseMove , false ); 1095 1096 } 1097 1098 kX.push(params.kX); 1099 kY.push(params.kY); 1100 1101 1102 }; 1103 1104 sGraf.animateLine = function ( path , speed ){ 1105 1106 if ( !path ) return; 1107 1108 var length = path.getTotalLength(); 1109 1110 // Clear any previous transition 1111 path.style.transition = path.style.WebkitTransition = 'none'; 1112 1113 // Set up the starting positions 1114 path.style.strokeDasharray = length + ' ' + length; 1115 path.style.strokeDashoffset = length; 1116 1117 // Trigger a layout so styles are calculated & the browser 1118 // picks up the starting position before animating 1119 path.getBoundingClientRect(); 1120 1121 // Define our transition 1122 path.style.transition = path.style.WebkitTransition = 'stroke-dashoffset ' + speed + ' ease-in-out'; 1123 1124 // Go! 1125 path.style.strokeDashoffset = '0'; 1126 1127 }; 1128 1129 sGraf.appendCircle = function ( parentNode , x , y , r , fill ){ 1130 1131 1132 var circle = sGraf.createElement('circle', { cx : x, cy : y , r : r, fill : fill } , true); 1133 1134 var speed = sGraf.randomInt(1 , 7) * 100; 1135 1136 sGraf.addAnimation( circle , { attributeName: 'r' , from : r * 10 , to : r , dur : speed +'ms' , repeatCount : 1}); 1137 sGraf.addAnimation( circle , { attributeName: 'opacity' , from : 0 , to : 0.7 , dur : speed * 1.5 + 'ms' , repeatCount : 1}); 1138 1139 parentNode.appendChild(circle); 1140 1141 1142 }; 1143 1144 sGraf.addAnimation = function( element, params , animationType ){ 1145 1146 var id = element.id || false; 1147 1148 if ( !id ){ 1149 id = 'animate' + Math.random(); 1150 element.id = id; 1151 } 1152 1153 animationType = animationType || 'animate'; 1154 1155 var animation = sGraf.createElement(animationType, params , true); 1156 1157 element.appendChild(animation); 1158 1159 1160 } 1161 1162 sGraf.randomInt = function(min, max) { 1163 return Math.floor(Math.random() * (max - min + 1)) + min; 1164 } 1165 1166 1167 sGraf.createValueBox = function ( params ) { 1168 1169 params = { 1170 1171 parent : params.parent ? params.parent : false, 1172 x : !isNaN(params.x) ? params.x : 10, 1173 y : !isNaN(params.y) ? params.y : 10, 1174 grafficId : !isNaN(params.grafficId) ? params.grafficId : false, 1175 grafficNumber : !isNaN(params.grafficNumber) ? params.grafficNumber : false 1176 1177 }; 1178 1179 var value_block; 1180 1181 if ( skin.valueBoxType == 1 ){ 1182 1183 value_block = sGraf.createElement('div', { id : 'v' + params.grafficId + '_' + params.grafficNumber, 'class' : 'value_box' }); 1184 1185 value_block.style.background = skin.colorsA[params.grafficNumber]; 1186 value_block.style.borderRadius = '3px'; 1187 value_block.style.padding = '2px 5px'; 1188 value_block.style.position = 'absolute'; 1189 value_block.style.opacity = 0; 1190 value_block.style.top = params.y + 'px'; 1191 value_block.style.color = skin.colors[params.grafficNumber]; 1192 value_block.style.transition = 'all 150ms ease-in'; 1193 1194 1195 } else if (skin.valueBoxType == 2) { 1196 1197 value_block = sGraf.createElement('div', { id : 'small_data_' + params.grafficId, 'class' : 'value_box' }); 1198 1199 value_block.style.background = 'rgba(0,0,0,.8)'; 1200 value_block.style.borderRadius = '3px'; 1201 value_block.style.padding = '7px 10px'; 1202 value_block.style.position = 'absolute'; 1203 value_block.style.opacity = 0; 1204 value_block.style.visibility = 'hidden'; 1205 value_block.style.fontSize = '13px'; 1206 value_block.style.top = -5 + 'px'; 1207 value_block.style.left = params.x + 'px'; 1208 value_block.style.color = '#eee'; 1209 value_block.style.transition = 'all 150ms ease-in'; 1210 1211 1212 1213 1214 var lang = navigator.language == 'ru' ? 0 : 1, 1215 texts = { 1216 1217 ru : { all : 'Ðа неделÑ' , today : 'СегоднÑ' }, 1218 en : { all : 'Week' , today : 'Today' } 1219 1220 }, 1221 counts = sGraf.takeDataCounters(grafficsData[params.grafficId]); 1222 content = ''.concat( 1223 1224 '<nobr>' , lang ? texts.en.all : texts.ru.all , ': <b>' , counts.all , '</b><br/>', '</nobr>', 1225 '<nobr>' , lang ? texts.en.today : texts.ru.today , ': <b>' , counts.today , '</b></nobr>' 1226 ); 1227 1228 1229 value_block.innerHTML = content; 1230 1231 } 1232 1233 value_block.dataset.number = params.grafficNumber; 1234 params.parent.parentNode.appendChild(value_block); 1235 1236 }; 1237 1238 sGraf.takeDataCounters = function ( data ) { 1239 1240 var all = 0, 1241 today = 0; 1242 1243 for (var i = data.length - 1; i >= 0; i--) { 1244 1245 1246 for (var j = data[i].length - 1; j >= 0; j--) { 1247 all += data[i][j]['count']; 1248 if ( data[i][j]['date'] == 7 ){ 1249 today += data[i][j]['count']; 1250 } 1251 } 1252 } 1253 1254 return { all : all , today : today }; 1255 1256 }; 1257 1258 sGraf.grafficHover = function ( e ) { 1259 1260 var id = e.currentTarget.dataset.id, 1261 valueTag = document.getElementById('small_data_' + id); 1262 1263 valueTag.style.visibility = 'visible'; 1264 valueTag.style.left = parseInt(valueTag.style.left , 10) + 10 + 'px'; 1265 valueTag.style.opacity = 1; 1266 1267 }; 1268 sGraf.grafficBlur = function ( e ) { 1269 1270 var id = e.currentTarget.dataset.id, 1271 valueTag = document.getElementById('small_data_' + id); 1272 1273 valueTag.style.left = parseInt(valueTag.style.left , 10) - 10 + 'px'; 1274 valueTag.style.opacity = 0; 1275 valueTag.style.visibility = 'hidden'; 1276 1277 1278 }; 1279 sGraf.grafficMouseMove = function ( e ) { 1280 1281 var x = e.layerX, 1282 y = e.layerY, 1283 id = e.currentTarget.dataset.id, 1284 xPos = Math.floor(x / kX[id]), 1285 yPos = Math.floor(y / kY[id]); 1286 1287 if ( e.target.className != 'value_box' ){ 1288 1289 for ( i = 0 ; i < grafficsData[id].length ; i++ ){ 1290 1291 var valueTag = document.getElementById('v' + id + '_' + i); 1292 1293 if ( valueTag && grafficsData[id][i][xPos] ){ 1294 1295 valueTag.innerHTML = grafficsData[id][i][xPos]['count']; 1296 valueTag.style.opacity = 1; 1297 1298 var newX = ( xPos ) * kX[id], 1299 newY = ( yPos ) * kY[id],
1300 marginBottom = !smallView ? 40 : 0; 1301 1302 // console.log( 250 - grafficsData[id][0][xPos]['count'] * kY ); 1303 1304 valueTag.style.left = newX + skin.leftLegendWidth + 'px'; 1305 valueTag.style.top = e.currentTarget.offsetHeight - skin.bottomLegendHeight - marginBottom - grafficsData[id][i][xPos]['count'] * kY[id] + 'px'; 1306 1307 } 1308 1309 } 1310 1311 } 1312 1313 1314 }; 1315 1316 1317 1318 1319 sGraf.createElement = function ( element , properties , isNS ) { 1320 1321 var nsUrl = 'http://www.w3.org/2000/svg'; 1322 1323 if ( !isNS ){ 1324 element = document.createElement( element ); 1325 } else { 1326 element = document.createElementNS( nsUrl , element ); 1327 } 1328 1329 1330 if ( properties ){ 1331 1332 for (var key in properties) { 1333 if (key == 'class') { 1334 element.className = properties[key]; 1335 } else if (key == 'id') { 1336 element.id = properties[key]; 1337 } else { 1338 // if ( !isNS ){ 1339 element.setAttribute(key, properties[key]); 1340 // } else { 1341 // element.setAttributeNS( nsUrl , key, properties[key]); 1342 // } 1343 } 1344 } 1345 1346 } 1347 1348 return element; 1349 1350 }; 1351 1352 1353 sGraf.drawBg = function ( ctx ){ 1354 1355 var img = document.getElementById('img'), 1356 width = 200, 1357 height = 200; 1358 1359 ctx.drawImage( img , 0 , 0 ); 1360 1361 var imageData = ctx.getImageData( 0 , 0 , img.width, img.height ); 1362 1363 pix = imageData.data; 1364 1365 1366 /* grayscale 1367 for ( var i = 0 ; i < pix.length; i += 4 ) { 1368 1369 var r = pix[i]; 1370 var g = pix[i+1]; 1371 var b = pix[i+2]; 1372 1373 // CIE luminance for the RGB 1374 // The human eye is bad at seeing red and blue, so we de-emphasize them. 1375 1376 var v = 0.2126 * r + 0.7152 * g + 0.0722 * b; 1377 1378 pix[i] = pix[i+1] = pix[i+2] = v; 1379 1380 } */ 1381 1382 sGraf.blur( 15 , ctx, img ); 1383 1384 // ctx.putImageData(imageData,0,0); 1385 1386 }; 1387 1388 1389 sGraf.mDown = function ( e ){ 1390 1391 var canvas = document.getElementById('canvas1'), 1392 context = canvas.getContext('2d'), 1393 x = e.layerX - canvas.offsetLeft, 1394 y = e.layerY - canvas.offsetTop; 1395 1396 1397 context.beginPath(); 1398 context.lineTo( x, y ); 1399 context.fillStyle = '#cbe2fa'; 1400 context.globalAlpha = 0.3; 1401 context.lineWidth = 3; 1402 // context.lineJoin = 'round'; 1403 1404 is_downed = true; 1405 1406 }; 1407 1408 sGraf.mMove = function ( e ){ 1409 1410 var canvas = document.getElementById('canvas1'), 1411 context = canvas.getContext('2d'), 1412 x = e.layerX - canvas.offsetLeft, 1413 y = e.layerY - canvas.offsetTop; 1414 1415 1416 1417 var infoX = x / kX >> 0; 1418 1419 // sGraf.redraw( canvas , sData, sTitles, infoX * kX ); 1420 1421 1422 }; 1423 1424 sGraf.mUp = function ( e ){ 1425 1426 var canvas = document.getElementById('canvas1'), 1427 context = canvas.getContext('2d'), 1428 x = e.layerX - canvas.offsetLeft, 1429 y = e.layerY - canvas.offsetTop; 1430 1431 1432 // context.arc( x , y , 6 , 0 , Math.PI * 2, false ); 1433 // context.fill(); 1434 context.closePath(); 1435 1436 1437 is_downed = false; 1438 1439 }; 1440 1441 sGraf.processClick = function ( e ){ 1442 1443 var canvas = document.getElementById('canvas1'), 1444 context = canvas.getContext('2d'), 1445 x = e.layerX - canvas.offsetLeft, 1446 y = e.layerY - canvas.offsetTop; 1447 1448 // console.log(e); 1449 1450 1451 // if (context.isPointInPath(x, y)){ 1452 1453 context.beginPath(); 1454 context.moveTo( x, y ); 1455 context.fillStyle = '#cbe2fa'; 1456 context.globalAlpha = 0.5; 1457 context.arc( x , y , 6 , 0 , Math.PI * 2, false ); 1458 context.fill(); 1459 context.closePath(); 1460 1461 // } 1462 1463 1464 // sGraf.redraw( canvas , {} ); 1465 1466 }; 1467 1468 1469 sGraf.blur = function ( strength , ctx , img ){ 1470 1471 ctx.globalAlpha = 0.1; // Higher alpha made it more smooth 1472 1473 // Add blur layers by strength to x and y 1474 // 2 made it a bit faster without noticeable quality loss 1475 1476 for (var y = -strength; y <= strength; y += 2) { 1477 1478 for (var x = -strength; x <= strength; x += 2) { 1479 1480 // Apply layers 1481 1482 ctx.drawImage(img, x, y); 1483 1484 1485 // Add an extra layer, prevents it from rendering lines 1486 // on top of the images (does makes it slower though) 1487 1488 if ( x>= 0 && y >= 0 ) { 1489 ctx.drawImage(img, -(x-1), -(y-1)); 1490 } 1491 } 1492 } 1493 ctx.globalAlpha = 1.0; 1494 1495 }; 1496 1497 1498 sGraf.convolute = function( pixels , weights, opaque ) { 1499 1500 var side = Math.round(Math.sqrt(weights.length)); 1501 var halfSide = Math.floor(side/2); 1502 var src = pixels.data; 1503 var sw = pixels.width; 1504 var sh = pixels.height; 1505 1506 // pad output by the convolution matrix 1507 var w = sw; 1508 var h = sh; 1509 var output = Filters.createImageData(w, h); 1510 var dst = output.data; 1511 1512 // go through the destination image pixels 1513 var alphaFac = opaque ? 1 : 0; 1514 1515 for (var y =0; y<h; y++) { 1516 1517 for (var x =0; x<w; x++) { 1518 1519 var sy = y; 1520 var sx = x; 1521 var dstOff = ( y * w + x ) * 4; 1522 1523 // calculate the weighed sum of the source image pixels that 1524 // fall under the convolution matrix 1525 var r = 0, 1526 g = 0, 1527 b = 0, 1528 a = 0; 1529 1530 for (var cy = 0 ; cy < side ; cy++ ) { 1531 1532 for (var cx=0; cx<side; cx++) { 1533 1534 var scy = sy + cy - halfSide; 1535 var scx = sx + cx - halfSide; 1536 1537 if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) { 1538 1539 var srcOff = ( scy * sw + scx ) * 4; 1540 var wt = weights[cy * side + cx]; 1541 1542 r += src[srcOff] * wt; 1543 g += src[srcOff+1] * wt; 1544 b += src[srcOff+2] * wt; 1545 a += src[srcOff+3] * wt; 1546 1547 } 1548 } 1549 } 1550 dst[dstOff] = r; 1551 dst[dstOff+1] = g; 1552 dst[dstOff+2] = b; 1553 dst[dstOff+3] = a + alphaFac*(255-a); 1554 1555 } 1556 1557 } 1558 1559 return output; 1560 1561 }; 1562 1563 sGraf.grayscale = function( pixels, args ) { 1564 1565 var d = pixels.data; 1566 1567 for ( var i = 0 ; i < d.length; i += 4 ) { 1568 1569 var r = d[i]; 1570 var g = d[i+1]; 1571 var b = d[i+2]; 1572 1573 // CIE luminance for the RGB 1574 // The human eye is bad at seeing red and blue, so we de-emphasize them. 1575 1576 var v = 0.2126 * r + 0.7152 * g + 0.0722 * b; 1577 1578 d[i] = d[i+1] = d[i+2] = v; 1579 1580 } 1581 1582 return pixels; 1583 1584 }; 1585 1586 /*********/ 1587 1588 1589 1590 1591 1592 1593 1594 return sGraf; 1595 1596}( {} );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.