I'm having an SVG with 2 layers (back, front).
I need to fill the back with a color (the color will be random).
But the front must stay as it is.
How can I fill the back without affecting the front?
PShape elem;
PShape back;
PShape front;
void setup()
{
size(900,600);
background(255);
fill(100);
elem = loadShape("resources/images/elem.svg");
back = elem.getChild("back");
front = elem.getChild("front");
smooth();
noLoop();
}
void draw(){
elem.disableStyle();
fill(0, 51, 102);
noStroke();
shape(back, 50, 50, 250, 250);
shape(front, 50, 50, 250, 250);
}
Thank you for your help.
Hard to test for your exact setup without the svg.
Still, you should be able to isolate drawing styles for parts of your shapes using pushStyle(),popStyle() pairs.
e.g.
PShape elem;
PShape back;
PShape front;
void setup()
{
size(900,600);
background(255);
fill(100);
elem = loadShape("resources/images/elem.svg");
back = elem.getChild("back");
front = elem.getChild("front");
smooth();
noLoop();
}
void draw(){
elem.disableStyle();
pushStyle();
fill(0, 51, 102);
noStroke();
shape(back, 50, 50, 250, 250);
popStyle();
pushStyle();
shape(front, 50, 50, 250, 250);
popStyle();
}
Indenting is just a visual cue, not actually needed.
Related
I have a basic program that essentially just displays an imported svg. Is there any way I can change the fill of the svg?
var img;
function preload() {
img = loadImage("assets/svgImage.svg")
}
function setup() {
createCanvas(720, 400);
background(200);
fill(204, 101, 192, 127);
stroke(127, 63, 120);
image(img, 50, 50, 50, 50)
}
I tried something along the lines of:
function setup() {
img.drawingContext.fillStyle = '#475731'
image(img, 50, 50, 50, 50)
}
But that doesn't seem to do anything for me.
http://zenozeng.github.io/p5.js-svg/examples/#manipulating
The example on the "Manipulating existing SVG" page says you need to use the querySVG function to obtain the path/shape components, then you can modify their fill attribute.
This is the example given:
var svg, path;
function preload() {
svg = loadSVG('test.svg');
frameRate(20);
}
function setup() {
createCanvas(600, 200, SVG);
image(svg, 0, 0, 200, 200);
path = querySVG('path')[1];
}
function draw() {
// update line width of 2nd line
path.attribute('stroke-width', frameCount % 20);
if (frameCount === 18) {
noLoop();
save(); // save current SVG graphics
}
}
I imagine in your case it would be:
path.attribute('fill', '#475731');
I have a circle, and then a triangle in the middle of the circle. I want to rotate the triangle around the center of the triangle. Kind of like rotating it 360 degrees. This is my code so far
public void paintComponent(Graphics g)
{
g.setColor(Color.BLACK);
g.drawArc(120, 120, 100, 100, 0, 360);
g.setColor(Color.RED);
int[] x = {160, 170, 180};
int[] y = {150, 190, 150};
g.drawPolygon(x, y, 3);
}
public static void main (String[] args)
{
JFrame frame = new JFrame("SpinningCircle");
frame.setSize(400, 400);
frame.setLocation(0, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new SpinningCircle());
frame.setVisible(true);
}
`
Thanks for help.
I am new to processing, currently I want to display a 3D ball and also add a text label to the 3D ball.
I am using the code as below:
// this function is called when this sketch is first loaded
void setup()
{
// choose size (width, height) of your sketch
size(720, 546, P3D);
// Choose background color for your sketch
background(0);
}
// This function is called repeatedly to draw stuff on screen.
void draw()
{
lights();
pushMatrix();
translate(500, height*0.35, 0);
fill(236,112,20);
noStroke();
sphere(40);
popMatrix();
//fill(255);
fill(255,112,20);
textAlign(CENTER);
textSize(15);
stroke(10);
text("hihihihi", 500, height*0.35);
}
It turned out that the text "hihihihi" is covered by the ball, but when I do it with 2D object it displays good. Is there anything wrong here, can anyone tell me what might be the problem of my code?Thanks!
Notice that your sphere has a radius of 40 which is means a diameter of 80 and you're drawing both the text and sphere at the same horizontal position(500).
Move the text to the right to avoid the sphere occluding it:
void setup()
{
size(720, 546, P3D);
background(0);
}
void draw()
{
lights();
pushMatrix();
translate(500, height*0.35, 0);
fill(236, 112, 20);
noStroke();
sphere(40);
popMatrix();
fill(255, 112, 20);
textAlign(CENTER);
textSize(15);
stroke(10);
text("hihihihi", 585, height*0.35);//make sure the text isn't occluded by anything else(like a sphere)
}
If you want to render text on a sphere I recommend trying PShape and PGraphics.
Here's a minimal example:
PShape sphere;
void setup()
{
size(720, 546, P3D);
background(0);
PGraphics sphereTexture = createGraphics(40,40);
sphereTexture.beginDraw();
sphereTexture.background(236, 112, 20);
sphereTexture.fill(255);
sphereTexture.text("Hi",20,20);
sphereTexture.endDraw();
sphere = createShape(SPHERE, 40);
sphere.disableStyle();
noStroke();
sphere.setTexture(sphereTexture);
}
void draw()
{
lights();
pushMatrix();
translate(500, height*0.35, 0);
fill(236, 112, 20);
noStroke();
shape(sphere,0,0);
popMatrix();
fill(255, 112, 20);
textAlign(CENTER);
textSize(15);
stroke(10);
text("hihihihi", 585, height*0.35);//make sure the text isn't occluded by anything else(like a sphere)
}
My OnPaint() function calls several other drawing functions.
void CGraph::OnPaint ()
{
CPaintDC dc(this);
// CMemDC DC(&dc);
dc.SetViewportOrg (0, 400);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(1000, 800);
dc.SetViewportExt(1000, -800);
ProcessData ();
DrawCoordinateSystem (&dc);
DrawGrid (&dc);
DrawGraph (&dc);
}
Example of DrawCoordianteSystem:
void CGraph::DrawCoordinateSystem (CDC* pDC)
{
CPen PenBlack (PS_SOLID, 1, RGB(0, 0, 0));
pDC->SelectObject (PenBlack);
// Rectangle round the system
pDC->Rectangle (0, -400, 1000, 400);
// Horizontal axis
pDC->MoveTo (0, 0);
pDC->LineTo (1000, 0);
pDC->SetTextColor (RGB(0,0,0));
pDC->SetBkColor (RGB(240, 240, 240));
pDC->TextOut (1001, 0, L"0");
// Vertical axis
pDC->MoveTo (0, -400);
pDC->LineTo (0, 400);
}
I now want to avoid flickering with CMemDC. However, i can't get it to work right. Can somebody show me how to implement CMemDC right?
Thanks
You need to load the memory DC with a bitmap to then BitBlt to the screen DC.
Try something like:
CDC dcMem;
CBitmap bitmap;
dcMem.CreateCompatibleDC( pDC );
bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height())
CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
... DO ALL YOUR DRAWING TO dcMem ...
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dcMem, 0, 0, SRCCOPY);
dcMem.SelectObject(pOldBitmap)
To avoid flickers you should draw everything on CMemDC and BitBlt it to the real DC.
Secondly add windows message handler for WM_ERASEBKGND message and change the code to
BOOL CGraph::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
My question is not about how to rotate text with Java2D; I know how to do that. What I don't know is how to make the rotated text "look good." For example, if you create a text box in PowerPoint and rotate it, the text appears sharp and clear no matter the rotation angle. However, text drawn with g2D.drawString() looks okay at 0 or 90 degrees but not so good at other angles. Is there a way to manipulate the text to clean or sharpen it up? If so, then if someone could point me to where look to learn how to do this I would be so thankful.
Below is a little program that illustrates what I'm talking about. The bigger font isn't too bad when rotated but still doesn't look very professional. The smaller font when rotated is terrible.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class RotateTest extends JPanel {
String message = "How does this text look?";
public RotateTest() {
this.setPreferredSize(new Dimension(640, 280));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2D.setFont(new Font("MyriadPro", Font.BOLD, 20));
g2D.drawString(message, 80, 20);
AffineTransform orig = g2D.getTransform();
double angle = Math.toRadians(7.0);
g2D.rotate(-angle, -10, 80);
g2D.drawString(message, 80, 80);
g2D.setTransform(orig);
angle = Math.toRadians(30.0);
g2D.rotate(-angle, -40, 80);
g2D.drawString(message, 60, 260);
g2D.setTransform(orig);
g2D.setFont(new Font("MyriadPro", Font.BOLD, 12));
g2D.drawString(message, 380, 20);
angle = Math.toRadians(7.0);
g2D.rotate(-angle, -10, 80);
g2D.drawString(message, 380, 120);
g2D.setTransform(orig);
angle = Math.toRadians(30.0);
g2D.rotate(-angle, -40, 80);
g2D.drawString(message, 320, 400);
g2D.setTransform(orig);
}
private void display() {
JFrame f = new JFrame("RotateTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new RotateTest().display();
}
});
}
}
I once had a similar problem, and solved it by drawing the text with high precision to an image, then drawing the rotated image.
Here's the code:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class RotatedText extends JPanel {
String message = "How does this text look?";
public RotatedText() {
this.setPreferredSize(new Dimension(640, 280));
}
public BufferedImage createStringImage(Graphics g, String s) {
int w = g.getFontMetrics().stringWidth(s) + 5;
int h = g.getFontMetrics().getHeight();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D imageGraphics = image.createGraphics();
imageGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
imageGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
imageGraphics.setColor(Color.BLACK);
imageGraphics.setFont(g.getFont());
imageGraphics.drawString(s, 0, h - g.getFontMetrics().getDescent());
imageGraphics.dispose();
return image;
}
private void drawString(Graphics g, String s, int tx, int ty, double theta, double rotx, double roty) {
AffineTransform aff = AffineTransform.getRotateInstance(theta, rotx, roty);
aff.translate(tx, ty);
Graphics2D g2D = ((Graphics2D) g);
g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2D.drawImage(createStringImage(g, s), aff, this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("MyriadPro", Font.BOLD, 20));
drawString(g, message, 80, 20, 0, 0, 0);
drawString(g, message, 80, 80, -Math.toRadians(7.0), -10, 80);
drawString(g, message, 60, 260, -Math.toRadians(30.0), -40, 80);
g.setFont(new Font("MyriadPro", Font.BOLD, 12));
drawString(g, message, 380, 20, 0, 0, 0);
drawString(g, message, 380, 120, -Math.toRadians(7.0), -10, 80);
drawString(g, message, 320, 400, -Math.toRadians(30.0), -40, 80);
}
private void display() {
JFrame f = new JFrame("RotateTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new RotatedText().display();
}
});
}
}
I haven't got the time to test this but will the following code help?:
Graphics2D g2d;
g2d.setRenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
This will only work on Graphics2D. If you're using normal Graphics you can cast your Graphics object to the 2D version like so:
Graphics2D g2d = (Graphics2D) g; //if Graphics object name is g.
Let me know!
Good luck