svgRandomColoredDots.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. /**
  3. * @created 09.07.2022
  4. * @author Smiley <smiley@chillerlan.net>
  5. * @copyright 2022 Smiley
  6. * @license MIT
  7. *
  8. * @see https://github.com/chillerlan/php-qrcode/discussions/136
  9. *
  10. * @noinspection PhpIllegalPsrClassPathInspection
  11. */
  12. use chillerlan\QRCode\Common\EccLevel;
  13. use chillerlan\QRCode\Data\QRMatrix;
  14. use chillerlan\QRCode\Output\QRMarkupSVG;
  15. use chillerlan\QRCode\{QRCode, QROptions};
  16. require_once __DIR__.'/../vendor/autoload.php';
  17. /*
  18. * Class definition
  19. */
  20. // the extended SVG output module
  21. class RandomDotsSVGOutput extends QRMarkupSVG{
  22. /**
  23. * To alter the layer a module appears on, we need to re-implement the collection method
  24. *
  25. * @inheritDoc
  26. */
  27. protected function collectModules(Closure $transform):array{
  28. $paths = [];
  29. // collect the modules for each type
  30. foreach($this->matrix->matrix() as $y => $row){
  31. foreach($row as $x => $M_TYPE){
  32. $M_TYPE_LAYER = $M_TYPE;
  33. if($this->options->connectPaths
  34. && $this->matrix->checkTypeNotIn($x, $y, $this->options->excludeFromConnect)
  35. ){
  36. // to connect paths we'll redeclare the $M_TYPE_LAYER to data only
  37. $M_TYPE_LAYER = QRMatrix::M_DATA;
  38. if($this->matrix->check($x, $y)){
  39. $M_TYPE_LAYER |= QRMatrix::IS_DARK;
  40. }
  41. }
  42. // randomly assign another $M_TYPE_LAYER for the given types
  43. // note that the layer id has to be an integer value,
  44. // ideally outside of the several bitmask values
  45. if($M_TYPE_LAYER === (QRMatrix::M_DATA | QRMatrix::IS_DARK)){
  46. $M_TYPE_LAYER = array_rand($this->options->dotColors);
  47. }
  48. // collect the modules per $M_TYPE
  49. $paths[$M_TYPE_LAYER][] = $transform($x, $y, $M_TYPE, $M_TYPE_LAYER);
  50. }
  51. }
  52. // beautify output
  53. ksort($paths);
  54. return $paths;
  55. }
  56. }
  57. // the extended options with the $dotColors option
  58. class RandomDotsOptions extends QROptions{
  59. /**
  60. * a map of $M_TYPE_LAYER => color
  61. *
  62. * @see \array_rand()
  63. */
  64. protected array $dotColors = [];
  65. }
  66. /*
  67. * Runtime
  68. */
  69. // our custom dot colors
  70. $dotColors = [
  71. 111 => '#e2453c',
  72. 222 => '#e07e39',
  73. 333 => '#e5d667',
  74. 444 => '#51b95b',
  75. 555 => '#1e72b7',
  76. 666 => '#6f5ba7',
  77. ];
  78. // generate the CSS for the several colored layers
  79. $layerColors = '';
  80. foreach($dotColors as $layer => $color){
  81. $layerColors .= sprintf("\n\t\t.qr-%s{ fill: %s; }", $layer, $color);
  82. }
  83. // prepare the options
  84. $options = new RandomDotsOptions([
  85. 'dotColors' => $dotColors,
  86. 'svgDefs' => '
  87. <style><![CDATA[
  88. .light{ fill: #dedede; }
  89. .dark{ fill: #424242; }
  90. '.$layerColors.'
  91. ]]></style>',
  92. 'version' => 5,
  93. 'eccLevel' => EccLevel::H,
  94. 'addQuietzone' => true,
  95. 'imageBase64' => false,
  96. 'outputType' => QRCode::OUTPUT_CUSTOM,
  97. 'outputInterface' => RandomDotsSVGOutput::class,
  98. 'markupDark' => '',
  99. 'markupLight' => '',
  100. 'imageTransparent' => true,
  101. 'connectPaths' => true,
  102. 'excludeFromConnect' => [
  103. QRMatrix::M_FINDER|QRMatrix::IS_DARK,
  104. QRMatrix::M_FINDER_DOT|QRMatrix::IS_DARK,
  105. QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK,
  106. ],
  107. 'drawCircularModules' => true,
  108. 'circleRadius' => 0.4,
  109. 'keepAsSquare' => [
  110. QRMatrix::M_FINDER|QRMatrix::IS_DARK,
  111. QRMatrix::M_FINDER_DOT|QRMatrix::IS_DARK,
  112. QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK,
  113. ],
  114. ]);
  115. // dump the output
  116. if(php_sapi_name() !== 'cli'){
  117. header('content-type: image/svg+xml');
  118. }
  119. echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
  120. exit;