Skip to content

Support for svg in React code. #31

Description

@ColeTownsend

Issuehunt badges

Supporting inline SVG

React by default can support inline svg code. Because NodeGUI does not render to a browser window though, we can't use that.

Possible Solutions
One solution might be to bridge QTSvg albeit I am not savvy enough to do this.

Sample code that triggered error

import React from 'react';
import { letterFrequency } from '@vx/mock-data';
import { Group } from '@vx/group';
import { Bar } from '@vx/shape';
import { scaleLinear, scaleBand } from '@vx/scale';

const data = letterFrequency;

const width = 500;
const height = 500;
const margin = { top: 20, bottom: 20, left: 20, right: 20 };

const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;

const x = (d: any) => d.letter;
const y = (d: any) => +d.frequency * 100;

const xScale = scaleBand({
  rangeRound: [0, xMax],
  domain: data.map(x),
  padding: 0.4,
});
const yScale = scaleLinear({
  rangeRound: [yMax, 0],
  domain: [0, Math.max(...data.map(y))],
});

const compose = (scale: any, accessor: any) => (data: any) => scale(accessor(data));
const xPoint = compose(
  xScale,
  x,
);
const yPoint = compose(
  yScale,
  y,
);

function BarGraph() {
  return (
    <svg width={width} height={height}>
      {data.map((d: any, i: any) => {
        const barHeight = yMax - yPoint(d);
        return (
          <Group key={`bar-${i}`}>
            <Bar x={xPoint(d)} y={yMax - barHeight} height={barHeight} width={xScale.bandwidth()} fill="#fc2e1c" />
          </Group>
        );
      })}
    </svg>
  );
}
export default BarGraph;
``


<!-- Issuehunt content -->

---

<details>
<summary>
<b>IssueHunt Summary</b>
</summary>


### Backers (Total: $20.00)

- $20.00 have been anonymously funded.
### Submitted pull Requests
- [#388 Add inline SVG support](https://oss.issuehunt.io/r/nodegui/react-nodegui/pull/388)
- [#389 Add SVG component support](https://oss.issuehunt.io/r/nodegui/react-nodegui/pull/389)
- [#392 fix(svg): quote true-valued XML attributes](https://oss.issuehunt.io/r/nodegui/react-nodegui/pull/392)
---

#### [Become a backer now!](https://oss.issuehunt.io/r/nodegui/react-nodegui/issues/31)
#### [Or submit a pull request to get the deposits!](https://oss.issuehunt.io/r/nodegui/react-nodegui/issues/31)
### Tips

- Checkout the [Issuehunt explorer](https://oss.issuehunt.io/r/nodegui/react-nodegui/) to discover more funded issues.
- Need some help from other developers? [Add your repositories](https://oss.issuehunt.io/r/new) on IssueHunt to raise funds.
</details>
<!-- /Issuehunt content-->

Activity

  1. issuehunt-oss commented on Nov 17, 2019

    @issuehunt-oss

    An anonymous user has funded $20.00 to this issue.


  2. danedavid commented on Dec 24, 2019

    @danedavid

    I reckon this should first be added as a class in nodegui, right?
    I'd like to work on this, if nobody is already working on it.

  3. a7ul commented on Dec 25, 2019

    @a7ul
    Collaborator

    Hi @danedavid
    To help you out a bit. Qt doesnt have separate native code for building svg.
    So few ways to do this:

    1. Use the QPainter (already available in Nodegui) and create a react api using that.
    2. Create a react api to generate svg string which would then be rendered as an svg image.

    So most probably you would only need to add missing methods in QPainter in Nodegui.

    If you have more ideas feel free to discuss them.

  4. danedavid commented on Dec 25, 2019

    @danedavid

    @master-atul Thank you for your quick reply!
    I was checking Qt docs yesterday ( first ever time ), and saw the QSvgWidget class which can load an SVG in serialized XML format as a QByteArray and can render the SVG. So at first look I was under the impression that was the way to go. Or am I completely off the tracks here?

  5. a7ul commented on Dec 25, 2019

    @a7ul
    Collaborator

    Hello @danedavid First of all Christmasintae ashamshakal 😄.

    As per the issue, we need Svg react components which we can use like this:

    function BarGraph() {
      return (
        <svg width={width} height={height}>
          {data.map((d: any, i: any) => {
            const barHeight = yMax - yPoint(d);
            return (
              <Group key={`bar-${i}`}>
                <Bar x={xPoint(d)} y={yMax - barHeight} height={barHeight} width={xScale.bandwidth()} fill="#fc2e1c" />
              </Group>
            );
          })}
        </svg>
      );
    }
    

    So if you see here we would need Group, Bar, SVG components.
    But, SVGWidget as you said takes a svg string (serialized xml).

    So what we can do is :
    when a user writes:

     <svg width={width} height={height}>
          {data.map((d: any, i: any) => {
            const barHeight = yMax - yPoint(d);
            return (
              <Group key={`bar-${i}`}>
                <Bar x={xPoint(d)} y={yMax - barHeight} height={barHeight} width={xScale.bandwidth()} fill="#fc2e1c" />
              </Group>
            );
          })}
        </svg>
    

    we can generate an xml string and then finally pass it to QSvgWidget.

    But the caveat is that any change in a prop we would need to regenerate entire svg string and pass it to SvgWidget which kindof defeats the purpose of React but is okay for initial mvp i think.

    The preferred way would be to create Svg, Group, Bar ,etc components that are based of QPainter (which is Qt's 2d drawing API).
    so when a user creates a tree of react components based on Svg, Group and Bar, etc we would actually draw it usnig QPainter. so any change in any of the prop react will just edit only that part.

    This is trickier but I can help you out all the way.

    PS: QSvgWidget class has been exported already via https://github.com/Ty3uK/nodegui-plugin-svg by @Ty3uK. It has both react and nodegui versions.

  6. danedavid commented on Dec 25, 2019

    @danedavid

    @master-atul, Merry Christmas to you too! 😁
    So basically, we're not going to support inline SVG in react code, but we're going to provide SVG-like components that'll allow the user to draw.
    Are we going to start by porting basic elements like <path>, <circle>, <rect> ? Or should it be a different API?

  7. Ty3uK commented on Dec 25, 2019

    @Ty3uK
    Contributor

    @danedavid yep, you're right. In my plugin I want to implement those elements in next step :)
    Also i've tried to use react-dom/server package to simply render components to string, but this approach not worked (crashes inside qode environment).

  8. danedavid commented on Dec 25, 2019

    @danedavid

    @Ty3uK Thanks for the input! And great work on the plugin! For someone to right away inject SVG into node-gui environment, your plugin is the way to go!

  9. Ty3uK commented on Dec 25, 2019

    @Ty3uK
    Contributor

    @danedavid thank you :) At this moment, plugin is only MVP, but I want to develop it further. If you want to contribute - you're welcome, let's do this together :)

  10. danedavid commented on Dec 29, 2019

    @danedavid

    @master-atul
    Some questions and thoughts on API design:

    1. What SVG components are we going to support? At least for the first cut, I was planning to include <SVG/>, <Rect/>, <Circle/>, <Ellipse>, <Line/>, <Polygon/>, along with their basic attributes.
    2. All components except SVG are valid only as children of SVG.
    3. The SVG will initialize an instance of QWidget ( or is there any other, more appropriate, canvas-like element in Qt? ). It will initialize a QPainter instance. Both instances will be passed down to all its children via context.
    4. Each child component will use the instances received via context to draw its own part.
  11. a7ul commented on Dec 29, 2019

    @a7ul
    Collaborator

    Yep, This seems like a good solution. Using Context on Svg component would ensure that Rect, Circle Ellipse and Line can only exist inside it.

  12. a7ul commented on Dec 29, 2019

    @a7ul
    Collaborator

    Let me know if you face any issue regarding QPainter or wrapping any component in React. I can help out!

  13. jswhisperer commented on Sep 19, 2020

    @jswhisperer

    that fork doesn't seem to work anymore... :( Error: Cannot find module 'got'
    I just want a circle in my application, and css border-radius: 50% doesnt seem to work either

  14. removed their assignment
    on Sep 19, 2020
  15. woahwhattheheck commented on Oct 8, 2026

    @woahwhattheheck

    Submitted PR #392 on this IssueHunt-funded issue — true-valued SVG/XML attributes are now quoted so boolean props serialize correctly. Claiming this submission's portion of the issue's funding per IssueHunt's ordinary process; prior contribution authorship preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions