QR SVG RENDER with Hearts #150
Replies: 5 comments 12 replies
-
Hey, yes, this would be possible with the SVG output module (dev-main, upcoming v5). The second example is possible with very few modifications - you would need to extend the protected function module(int $x, int $y, int $M_TYPE):string{
if(!$this->options->drawLightModules && !$this->matrix->check($x, $y)){
return '';
}
// modify the output of circular modules to return hearts instead
// you can then use the respective option values to modify the behaviour
if($this->options->drawCircularModules && $this->matrix->checkTypeNotIn($x, $y, $this->options->keepAsSquare)){
return sprintf('M%1$s %2$s m0.5,0.96 l-0.412,-0.412 a0.3 0.3 0 0 1 0.412,-0.435 a0.3 0.3 0 0 1 0.412,0.435Z', $x, $y);
}
return sprintf('M%1$s %2$s h1 v1 h-1Z', $x, $y);
} If you want to keep the circular modules, you'd need to add your own option values of course - you can find an example for that over here. The path segment starts at the position of the module ($x, $y - top left corner) and is drawn with relative coordinates from there. You can find an example of shapes and positioning in this SVG image. The first example is a bit more complex but can be solved by checking for the Unfortunately it's not easy to convert an SVG image to a raster format in PHP with Imagick without losses, so you would instead need to call the Inkscape command line tool. |
Beta Was this translation helpful? Give feedback.
-
So i made a quick example of how to modify the finder patterns and use custom shapes for them. As i mentioned before, there are several ways of achieving this. class QRSvgWithLogoAndCustomShapes extends QRMarkupSVG{
/**
* @inheritDoc
*/
protected function paths():string{
// make sure connect paths is enabled
$this->options->connectPaths = true;
// empty the default value to remove the fill* attributes from the <path> elements
$this->options->markupDark = '';
$this->options->markupLight = '';
$size = (int)ceil($this->moduleCount * $this->options->svgLogoScale);
// we're calling QRMatrix::setLogoSpace() manually, so QROptions::$addLogoSpace has no effect here
$this->matrix->setLogoSpace($size, $size);
// generate the path element(s) - in this case it's just one element as we've "disabled" several options
$svg = parent::paths();
// now we're lazy modifying the generated path to add the custom shapes for the finder patterns
$svg = str_replace('"/>', $this->getFinderPatterns().'"/>', $svg);
// and add the custom logo
$svg .= $this->getLogo();
return $svg;
}
/**
* returns a path segment for a single module
*
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
*/
protected function module(int $x, int $y, int $M_TYPE):string{
if(
!$this->matrix->check($x, $y)
// we're skipping the finder patterns here
|| $this->matrix->checkType($x, $y, QRMatrix::M_FINDER)
|| $this->matrix->checkType($x, $y, QRMatrix::M_FINDER_DOT)
){
return '';
}
// return a heart shape (or any custom shape for that matter)
return sprintf('M%1$s %2$s m0.5,0.96 l-0.412,-0.412 a0.3 0.3 0 0 1 0.412,-0.435 a0.3 0.3 0 0 1 0.412,0.435Z', $x, $y);
}
/**
* returns a custom path for the 3 finder patterns
*/
protected function getFinderPatterns():string{
$qz = $this->options->addQuietzone ? $this->options->quietzoneSize : 0;
// the positions for the finder patterns (top left corner)
// $this->moduleCount includes 2* the quiet zone size already so we need to take this into account
$pos = [
[0 + $qz, 0 + $qz],
[0 + $qz, $this->moduleCount - $qz - 7],
[$this->moduleCount - $qz - 7, 0 + $qz],
];
// the custom path for one finder pattern - the first move (M) is parametrized, the rest are relative coordinates
$path = 'M%1$s,%2$s m2,0 h3 q2,0 2,2 v3 q0,2 -2,2 h-3 q-2,0 -2,-2 v-3 q0,-2 2,-2z m0,1 q-1,0 -1,1 v3 q0,1 1,1 h3 q1,0 1,-1 v-3 q0,-1 -1,-1z m0,2.5 a1.5,1.5 0 1 0 3,0 a1.5,1.5 0 1 0 -3,0Z';
$finder = [];
foreach($pos as $coord){
[$ix, $iy] = $coord;
$finder[] = sprintf($path, $ix, $iy);
}
return implode(' ', $finder);
}
/**
* returns a <g> element that contains the SVG logo and positions it properly within the QR Code
*
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform
*/
protected function getLogo():string{
// @todo: customize the <g> element to your liking (css class, style...)
return sprintf(
'%5$s<g transform="translate(%1$s %1$s) scale(%2$s)" class="%3$s">%5$s %4$s%5$s</g>',
($this->moduleCount - ($this->moduleCount * $this->options->svgLogoScale)) / 2,
$this->options->svgLogoScale,
$this->options->svgLogoCssClass,
file_get_contents($this->options->svgLogo),
$this->options->eol
);
}
} |
Beta Was this translation helpful? Give feedback.
-
I was playing around a bit with this example. I'd like to have the Finder markers more rounded like this, but inside not a circle. How do you create such a simple path? I make an SVG with a rounded square marker in the middle.
However, I can't find a way to change the path back to the example like: I get that If you can help me with this, that would be great. By the way for people reading this too. I didn't wanted the hearts so I changed it back to the circle:
|
Beta Was this translation helpful? Give feedback.
-
it's once again me! is there a possibility to define the SIZE of the created QR Code which is generated as PNG in PX e.g. 2000x2000px? |
Beta Was this translation helpful? Give feedback.
-
Hello im not able to put logo center of it can you help and also the hearth shape is not working too |
Beta Was this translation helpful? Give feedback.
-
Hi! I wanted to check with the group and see if this would be also beneficial to any of them.
1.) We want to use Chillerlan solution to create a beautiful QR code looking like this:
2.) in a second step the QR Code should be combined to a existing SVG or PNG with exact coordinates..
Is there a possibility to do this with Chillerlan? And how is the right way to achieve this?
Thanks a lot for Help!
BR Mike
Beta Was this translation helpful? Give feedback.
All reactions