Delete rather than hide area outside clipPath SVG (React-Native) - react-native

I am creating a jigsaw puzzle in React Native ios. I have paths and one image, I am using a loop to create SVG elements of each puzzle piece. However, when I use Draggable from 'react-native-draggable' to drag each piece, I realize that the clipPath to create the pieces only hides the rest of the image rather than deleting it, so the draggable is available on the whole image rather than just the piece.
This is my code for generating a list of the pieces which I just render in my return function as {pieces}:
const gen = () => {
let xC = 5, yC = 7;
let width = 380, height = 540;
let piece_width = Math.floor(width / xC), piece_height = Math.floor(height / yC);
const out = new JigsawGenerator({ width: width, height: height, xCount: xC, yCount: yC, radius: 20, fixedPattern: false });
let cells = out["cells"]; // 2d array of paths
let pieces = [];
let k = 0;
for (let i = 0; i < cells.length; i++) {
for (let j = 0; j < cells[i].length; j++) {
let p = cells[i][j];
pieces.push(
<Draggable>
<SVG.Svg
width={width}
height={height}
fill="none"
key={k}
>
<SVG.Defs>
<SVG.ClipPath id="clip" >
<SVG.Path
d={p}
stroke="black"
strokeWidth={3}
strokeLinecap="round"
strokeLinejoin="round"
/>
</SVG.ClipPath>
</SVG.Defs>
<SVG.Image
width={width}
height={height}
preserveAspectRatio="xMidYMid slice"
href={img_src}
clipPath="url(#clip)"
/>
</SVG.Svg>
</Draggable>
);
k++;
}
};
return pieces;
};
This is an example of what one of the pieces looks like, with a border around the SVG element. I just want the piece itself to be clickable/draggable, but I can drag from anywhere inside the border and the whole rectangle is dragged:
example singular jigsaw piece
I would really appreciate if anyone had any ideas on how to make it so that the area outside the clipPath is deleted/won't be included in Draggable!

Related

How to make hexagon shape image in react native?

I want to make hexagon shape image like as below image but didn't find any perticular way to make it customized.
Here is the image:
Suggest any library to make it possible in react-native.
So I thought that the usage of a hexagon path was so common that finding an existing one online would be a simple task, but searches proved to be fruitless so I decided to make a function that would make a regular hexagon Skia Path. I found a really cool quora answer on how to get the points any size hexagon(regular hexagon), and then I just connect the points:
import {Skia} from "#shopify/react-native-skia";
function makeHexagonPath(size, offset) {
const path = Skia.Path.Make();
let [xOffset, yOffset] = offset || [0, 0];
if (!size) size = 10;
// https://www.quora.com/How-can-you-find-the-coordinates-in-a-hexagon
const halfed = size / 2;
const sqrt = (Math.sqrt(3) * size) / 2;
const points = [
[size, 0], //a
[halfed, sqrt], //b
[-halfed, sqrt], //c
[-size, 0], //d
[-halfed, -sqrt], //e
[halfed, -sqrt], //f
].map(([x, y]) => [x + xOffset, y + yOffset]);
console.log(points);
path.moveTo(...points[0]);
points.forEach((point) => path.lineTo(...point));
path.close();
return path;
}
With the makeHexagonPath function you draw a clipping of any size and use the offset parameter to move the hexagon to desired location:
const imageSize = 200
export default function ClipImage({imageSrc}) {
const image = useImage(imageSrc);
const hexagonSize = imageSize / 2;
const path = makeHexagonPath(hexagonSize, [hexagonSize, hexagonSize]);
if (!image) return null;
return (
<Group clip={path}>
/*<Path path={path} color="lightblue" />*/
<Image
image={image}
fit="cover"
x={0}
y={0}
width={imageSize}
height={imageSize}
/>
</Group>
);
}
I would post an expo snack demoing it but react-native-skia wasnt working for me on expo but in the default react-native environment it worked like a charm

Align UI lements correctly in SkiaSharp (UWP)

I am trying to align a few buttons in a circular manner using SkiaSharp. My code looks like this
<skia:SKXamlCanvas x:Name="test" PaintSurface="Test_OnPaintSurface" />
Code behind
private void Test_OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
// the canvas and properties
var canvas = e.Surface.Canvas;
// get the screen density for scaling
var display = DisplayInformation.GetForCurrentView();
var scale = display.LogicalDpi / 96.0f;
var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale);
// handle the device screen density
canvas.Scale(scale);
// make sure the canvas is blank
canvas.Clear(SKColors.Transparent);
// draw some text
var paintSmallCircle = new SKPaint
{
Color = SKColors.CornflowerBlue,
IsAntialias = true,
Style = SKPaintStyle.Fill,
TextAlign = SKTextAlign.Center,
TextSize = 24
};
var paintCircle = new SKPaint
{
Color = SKColors.LightGray,
IsAntialias = true,
Style = SKPaintStyle.Fill,
TextAlign = SKTextAlign.Center,
TextSize = 24
};
var coord = new SKPoint(
scaledSize.Width / 2,
(scaledSize.Height) / 2);
canvas.DrawCircle(coord, 120, paintCircle);
int r = 100;
int angle = 90;
for (int i = 0; i < 12; i++)
{
double x1 = scaledSize.Width / 2 + r * Math.Cos(Math.PI * angle / 180.0) ;
double y1 = scaledSize.Height / 2 - r * Math.Sin(Math.PI * angle / 180.0) ;
var coord1 = new SKPoint((float) x1, (float)y1);
canvas.DrawCircle(coord1, 10, paintSmallCircle);
Button btn = new Button { Content = i, Height = 25, Width = 25, };
btn.SetValue(SKXamlCanvas.LeftProperty, coord1.X);
btn.SetValue(SKXamlCanvas.TopProperty, coord1.Y);
test.Children.Add(btn);
angle = angle - 30;
}
}
With this code, I am able to draw Blue circles correctly, but the button alignment comes wrong. How can I solve this issue?
right now my output looks like this
As you can see blue small circles are aligned correctly, but not buttons.
The expected behavior is that buttons come in the same place where blue circles are rendered
The point is you place the Button's Left & Top property.
When you use canvas.DrawCircle(coord1, 10, paintSmallCircle); to draw a Circle, the center point is coord1.
And you draw the Buttons Left & Top at the center point of the Circle.
So you can draw Button using
btn.SetValue(SKXamlCanvas.LeftProperty, coord1.X - 25 /2);
btn.SetValue(SKXamlCanvas.TopProperty, coord1.Y - 25 / 2);
25 is the Height and Width of your Button.
See the result.

Adding sprite in PIXI Particles Container using Vue.js

I have a problem adding a Sprite to my PIXI Particles container in Vue.js. This works when I run PIXI only inside a script, but somehow in Vuejs every new PIXI.Sprite.from("../assets/plainSquare.png") don't show
My goal is to generate a static grid of square this way:
setup() {
// making a 30 x 16 grid of tiles
const columns = 30;
const rows = 16;
for (let i = 0; i < columns * rows; i++) {
const square = PIXI.Sprite.from("../assets/plainSquare.png");
square.width = square.height = 25;
square.x = (i % columns) * 32;
square.y = Math.floor(i / columns) * 32;
// add squares to stage
this.container.addChild(square);
}
}
If you need, here is the full codesanbox: https://codesandbox.io/s/pixi-sprite-loading-cn7re?file=/src/App.vue
Use require for get the image:
PIXI.Sprite.from( require("./assets/plainSquare.png"));

Resizing a Rectangle inside a GridPane using percentage ColumnConstraints

I have a GridPane with n columns & n rows, and a Rectangle in each cell (almost like a chess board). I'm trying to make the Rectangles expand to take up all the space available in each cell, without expanding too far. Have tried a ColumnConstraints approach, but still don't know what to bind the Rectangles' width to.
Solution: bind Rectangle width and height to a NumberBinding.
Example, makes a chess board:
GridPane board = new GridPane();
NumberBinding rectsAreaSize = Bindings.min(board.heightProperty(), board.widthProperty());
for(int i = 0; i < size; ++i)
{
for(int j = 0; j < size; ++j)
{
Rectangle rect;
if(i % 2 == 0 ^ j % 2 == 0) // ^ is the XOR operator
{
rect = new Rectangle(15.0, 15.0, Color.WHITE);
}
else
{
rect = new Rectangle(15.0, 15.0, Color.BLACK);
}
rect.widthProperty().bind(rectsAreaSize.divide(size));
rect.heightProperty().bind(rectsAreaSize.divide(size));
board.add(rect, i, j);
GridPane.setHalignment(rect, HPos.CENTER);
}
}
References:
How to create dynamically Resizable shapes in javafx?
Can a gridpane automatically resize it's objects to fit? Trying to set a max_width and max_height to a grid and have it resize content. JavaFX

Rotating camera around the X-axis (three.js)

I am trying to rotate the camera around to X-axis of the scene.
At this point my code is like this:
rotation += 0.05;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
This makes the camera move around but during the rotation something weird happens and either the camera flips, or it skips some part of the imaginary circle it's following.
You have only provided a snippet of code, so I have to make some assumptions about what you are doing.
This code:
rotation += 0.05;
camera.position.x = 0;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
camera.lookAt( scene.position ); // the origin
will cause the "flipping" you refer to because the camera is trying to remain "right side up", and it will quickly change orientation as it passes over the "north pole."
If you offset the camera's x-coordinate like so,
camera.position.x = 200;
the camera behavior will appear more natural to you.
Three.js tries to keep the camera facing up. When you pass 0 along the z-axis, it'll "fix" the camera's rotation. You can just check and reset the camera's angle manually.
camera.lookAt( scene.position ); // the origin
if (camera.position.z < 0) {
camera.rotation.z = 0;
}
I'm sure this is not the best solution, but if anyone else runs across this question while playing with three.js (like I just did), it'll give one step further.
This works for me, I hope it helps.
Rotating around X-Axis:
var x_axis = new THREE.Vector3( 1, 0, 0 );
var quaternion = new THREE.Quaternion;
camera.position.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
camera.up.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
Rotating around Y-Axis:
var y_axis = new THREE.Vector3( 0, 1, 0 );
camera.position.applyQuaternion(quaternion.setFromAxisAngle(y_axis, angle));
Rotating around Z-Axis:
var z_axis = new THREE.Vector3( 0, 0, 1 );
camera.up.applyQuaternion(quaternion.setFromAxisAngle(z_axis, angle));
I wanted to move my camera to a new location while having the camera look at a particular object, and this is what I came up with [make sure to load tween.js]:
/**
* Helper to move camera
* #param loc Vec3 - where to move the camera; has x, y, z attrs
* #param lookAt Vec3 - where the camera should look; has x, y, z attrs
* #param duration int - duration of transition in ms
**/
function flyTo(loc, lookAt, duration) {
// Use initial camera quaternion as the slerp starting point
var startQuaternion = camera.quaternion.clone();
// Use dummy camera focused on target as the slerp ending point
var dummyCamera = camera.clone();
dummyCamera.position.set(loc.x, loc.y, loc.z);
// set the dummy camera quaternion
var rotObjectMatrix = new THREE.Matrix4();
rotObjectMatrix.makeRotationFromQuaternion(startQuaternion);
dummyCamera.quaternion.setFromRotationMatrix(rotObjectMatrix);
dummyCamera.up.set(camera)
console.log(camera.quaternion, dummyCamera.quaternion);
// create dummy controls to avoid mutating main controls
var dummyControls = new THREE.TrackballControls(dummyCamera);
dummyControls.target.set(loc.x, loc.y, loc.z);
dummyControls.update();
// Animate between the start and end quaternions
new TWEEN.Tween(camera.position)
.to(loc, duration)
.onUpdate(function(timestamp) {
// Slerp the camera quaternion for smooth transition.
// `timestamp` is the eased time value from the tween.
THREE.Quaternion.slerp(startQuaternion, dummyCamera.quaternion, camera.quaternion, timestamp);
camera.lookAt(lookAt);
})
.onComplete(function() {
controls.target = new THREE.Vector3(scene.children[1].position-0.001);
camera.lookAt(lookAt);
}).start();
}
Example usage:
var pos = {
x: -4.3,
y: 1.7,
z: 7.3,
};
var lookAt = scene.children[1].position;
flyTo(pos, lookAt, 60000);
Then in your update()/render() function, call TWEEN.update();
Full example