I can't get this map generator to work properly - javascript

The image that I want to get:
Image 1
The image that I'm getting when I run my code:
Image 2
To get the first image, you have to choose the tiny option in "number of regions", disable the check marks "noisy edges", "noisy fills" and "icons" in the site: link
My code is below, if you go to the site link and inspect it, you will see all the modules, is easy to see. In the draw.js file I edited document.createElement('canvas') to new Canvas.Canvas(), and I put var Canvas = require('canvas') in there too, theses things are the only thing that I edited (If I'm not mistaken) in all the modules. I'm running the code with node.
var fs = require('fs');
var Canvas = require('canvas')
const SimplexNoise = require('./simplex-noise/simplex-noise.js');
const Poisson = require('./poisson-disk-sampling/poisson-disk-sampling.js');
const DualMesh = require('./dual-mesh/index.js');
const MeshBuilder = require('./dual-mesh/create.js');
const Map = require('./mapgen2/index.js');
const Draw = require('./draw.js');
const Colormap = require('./colormap.js');
const {makeRandInt, makeRandFloat} = require('./prng/index.js');
let defaultUiState = {
seed: 187,
variant: 0,
size: 'tiny',
'noisy-fills': false,
'noisy-edges': false,
icons: false,
biomes: false,
lighting: false,
'north-temperature': 0,
'south-temperature': 0.05,
rainfall: 0,
canvasSize: 0,
persistence: 0, /* 0 means "normal" persistence value of 1/2 */
};
let uiState = {};
Object.assign(uiState, defaultUiState);
let _mapCache = [];
function getMap(size) {
const spacing = {
tiny: 38,
small: 26,
medium: 18,
large: 12.8,
huge: 9,
};
if (!_mapCache[size]) {
let mesh = new MeshBuilder({boundarySpacing: spacing[size]})
.addPoisson(Poisson, spacing[size], makeRandFloat(12345))
.create();
_mapCache[size] = new Map(
new DualMesh(mesh),
{amplitude: 0.2, length: 4, seed: 12345},
makeRandInt
);
console.log(`Map size "${size}" has ${_mapCache[size].mesh.numRegions} regions`);
}
return _mapCache[size];
}
let requestAnimationFrameQueue = [];
const mapIconsConfig = {left: 9, top: 4, filename: "./map-icons.png"};
mapIconsConfig.image = new Canvas.Image();
mapIconsConfig.image.onload = draw;
mapIconsConfig.image.src = mapIconsConfig.filename;
function draw() {
let map = getMap(uiState.size);
let noisyEdges = uiState['noisy-edges'],
noisyFills = uiState['noisy-fills'];
let canvas = new Canvas.Canvas(1000, 1000);
let ctx = canvas.getContext('2d');
let size = Math.min(canvas.width, canvas.height);
if (size != uiState.canvasSize) {
uiState.canvasSize = size;
size = 1024;
canvas.width = size;
canvas.height = size;
}
let noise = new SimplexNoise(makeRandFloat(uiState.seed));
let persistence = Math.pow(1/2, 1 + uiState.persistence);
let islandShapeAmplitudes = Array.from({length: 5}, (_,octave) => Math.pow(persistence, octave));
let biomeBias = {
north_temperature: uiState['north-temperature'],
south_temperature: uiState['south-temperature'],
moisture: uiState.rainfall,
};
let colormap = uiState.biomes? new Colormap.Discrete() : new Colormap.Smooth();
let queue = [];
if ((!noisyEdges || uiState.size === 'large' || uiState.size === 'huge')) {
queue.push(() => Draw.approximateIslandShape(ctx, 1000, 1000, noise, {round: 0.5, inflate: 0.4, amplitudes: islandShapeAmplitudes.slice(0, 3)}));
}
queue.push(
() => map.calculate({
noise: noise,
drainageSeed: uiState.variant,
riverSeed: uiState.variant,
biomeBias: biomeBias,
shape: {round: 0.5, inflate: 0.4, amplitudes: islandShapeAmplitudes},
}),
() => {
Draw.background(ctx, colormap);
Draw.noisyRegions(ctx, map, colormap, noisyEdges);
// Draw the rivers early for better user experience
Draw.rivers(ctx, map, colormap, noisyEdges, true);
}
);
for (let phase = 0; phase < 16; phase++) {
queue.push(() => Draw.noisyEdges(ctx, map, colormap, noisyEdges, phase));
}
queue.push(() => Draw.rivers(ctx, map, colormap, noisyEdges, false));
queue.push(() => Draw.coastlines(ctx, map, colormap, noisyEdges));
if (noisyFills) {
queue.push(() => Draw.noisyFill(ctx, 1000, 1000, makeRandInt(12345)));
}
if (uiState.icons) {
queue.push(() => Draw.regionIcons(ctx, map, mapIconsConfig, makeRandInt(uiState.variant)));
}
if (uiState.lighting) {
queue.push(() => Draw.lighting(ctx, 1000, 1000, map));
}
requestAnimationFrameQueue = queue.map(
(layer, i) => () => {
ctx.save();
ctx.scale(canvas.width / 1000, canvas.height / 1000);
layer();
ctx.restore();
});
while (requestAnimationFrameQueue.length > 0) {
let f = requestAnimationFrameQueue.shift();
f();
}
return canvas;
}
function saveToFile(canvas) {
const buff = canvas.toBuffer();
fs.writeFileSync("test.png", buff, {encoding: "utf-8", flag: "w+", mode: 0o666});
}
let canvas = draw();
saveToFile(canvas);

Related

How to spawn collectables or pickups in patterns and at random positions using Phaser 3

I am Making a 2d endless runner using Phaser 3 and I need to spawn coins and other pickups in random positions and also in different patterns such as diamond shape, square,...
I don't really have much code and I do not know how to go about it. I would gladly appreciate any help in any way. Thank you.
It depends on your code-structure, but I would use the builtin function Phaser.Math.Between, to generate random positions/numbers (link to the documentation).
(Sidenote: The first examples are made for arcade physics, the final one with is made for matter.js )
Here is a very simple approach:
In code:
The interval in which coins are spawned is random
setTimeout(_ => this.loadCoins(coins), Phaser.Math.Between(2500, 3000));
The position of the pickup is random
let yCoord = Phaser.Math.Between(20, 180);
let xCord = 400 + Phaser.Math.Between(0, 100);
The pickup type is random
let coinType = Phaser.Math.Between(0, 2);
and te amount of coins to spawn
let coinsToSpawn = Phaser.Math.Between(1, 5);
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
}
loadCoins(coins){
let coin;
// Generate random amount of coins each time
let coinsToSpawn = Phaser.Math.Between(1, 5);
for(let i = 0; i < coinsToSpawn; i++){
// Get Random y position (x is always bigger than the scene width)
let yCoord = Phaser.Math.Between(20, 180);
let xCord = 400 + Phaser.Math.Between(0, 100);
// Randomly generate types
let coinType = Phaser.Math.Between(0, 2);
switch(coinType){
case 0:
coin = this.add.rectangle(xCord, yCoord, 15, 15, 0xFFFF00);
break;
case 1:
coin = this.add.circle(xCord, yCoord, 7, 0xFF0000);
break;
case 2:
coin = this.add.star(xCord, yCoord, 5, 5, 15, 0x00FF00);
break;
}
coin = this.physics.add.existing(coin);
coins.add(coin);
}
coins.setVelocityX(-100);
// Start next Coin loading randomly in 2.5 - 3 Seconds
setTimeout(_ => this.loadCoins(coins), Phaser.Math.Between(2500, 3000));
}
create() {
this.player = this.add.rectangle(200, 100, 20, 20, 0xffffff);
this.physics.add.existing(this.player);
//Add World Physics
this.physics.world.setBounds(0, 0, 400, 200);
this.player.body.setCollideWorldBounds(true);
this.player.body.setImmovable(true);
let coins = this.physics.add.group({immovable: true, allowGravity: false});
this.loadCoins(coins);
this.physics.add.collider(this.player, coins,
(player, coin) => {
coin.destroy();
});
}
}
const config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: [ GameScene ],
physics: {
default: 'arcade',
}
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
Update (create shapes with coins):
-> Check out some cool builtin functions in the Phaser.Actions Namespace (like to the documentation).
like _(to name a few)):
Phaser.Actions.PlaceOnCircle
Phaser.Actions.PlaceOnLine
Phaser.Actions.PlaceOnTriangle
...
Disclaimer: This code is not optimal is just created like this to proof the point.
UPDATE for spawning:
Sidenotes:
the spawn has to be trigger, so I use setInterval, but you can use events, user input, or simply in the update function, or ...
the cleanup and the saving of the groups could be handled better, but it's a demo.
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
//keep reference to the groups
this.coinGroups = [];
}
spawnCoins(){
let coins = this.physics.add.group({immovable: true, allowGravity: false});
var circle = new Phaser.Geom.Circle(440, 80, 40);
for(let i = 0; i < 10; i++){
let coin = this.add.circle(0, 0, 8, 0xFFFF00);
coin = this.physics.add.existing(coin);
coins.add(coin);
}
coins.setVelocityX(-100);
this.coinGroups.push(coins);
Phaser.Actions.PlaceOnCircle(coins.getChildren(), circle);
}
create() {
this.add.text(10,10,'Spawing every 2sec')
.setColor('#ffffff');
// Spawing ever 2 Sec
setInterval( _ => {
this.spawnCoins();
}, 2000);
}
update(){
// Minor Cleanup
for(let group of this.coinGroups){
group.getChildren().forEach(child => {
if(child.x < 0){
group.remove(child, true, true);
}
});
}
this.coinGroups = this.coinGroups.filter(group => group.length > 0 );
}
}
const config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: [ GameScene ],
physics: {
default: 'arcade',
}
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
Mini demo with matter.js:
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
//keep reference to the groups
this.coinGroups = [];
}
spawnCoins(){
// standart Phaser Group
let coins = this.add.group();
var circle = new Phaser.Geom.Circle(440, 80, 40);
for(let i = 0; i < 10; i++){
let coin = this.matter.add.image(50, 50, 'coin').setOrigin(.5);
coin.setIgnoreGravity(true);
coin.setVelocityX(-3);
coin.setFrictionAir(0);
coins.add(coin);
}
this.coinGroups.push(coins);
Phaser.Actions.PlaceOnCircle(
coins.getChildren(), circle);
}
create() {
this.add.text(10, 10, 'Coins spawned every second')
.setOrigin(0)
.setColor('#ffffff');
// Just creating a texture/image for matter
let g = this.make.graphics({x: 0, y: 0, add: false});
g.fillStyle(0xffff00);
g.fillCircle(7, 7, 7);
g.generateTexture('coin', 14, 14);
setInterval( _ => this.spawnCoins(), 1000);
}
update(){
// Clean Up
for(let group of this.coinGroups){
group.getChildren().forEach(child => {
if(child.x < 0){
group.remove(child, true, true);
}
});
}
this.coinGroups = this.coinGroups.filter(group => group.getChildren().length > 0);
}
}
const config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: [ GameScene ],
physics: {
default: 'matter'
},
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>

Potree library not working consistently in react js

I have integrated potree in my react web app to render 3D models and point cloud. Whenever I load it for first time it renders and loads the 3D model without any hassle, but if the page is refreshed or revisited it fails to load. Prompts the error - Potree is undefined.
How to solve this ?
Here is my code snippet.
import React from 'react';
import styled from "styled-components/macro";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader.js"
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
import * as THREE from 'three';
const Wrapper = styled.div`
background-color: black;
display: flex;
flex-direction: column;
height: 675px;
position: relative;
`;
// import vanillaJS Potree libs, /!\ would be best with proper ES6 import
export default class PointcloudNavigator extends React.Component {
constructor(props) {
super(props)
this.potreeContainerDiv = React.createRef();
}
render() {
return (
<div id="potree-root">
<Wrapper ref={this.potreeContainerDiv} className={"potree_container "}>
<div id="potree_render_area"></div>
</Wrapper>
</div>
)
}
addLights = () => {
const lights = [];
lights[0] = new THREE.PointLight(0xffffff, 1.2, 0);
lights[1] = new THREE.PointLight(0xffffff, 1.2, 0);
lights[2] = new THREE.PointLight(0xffffff, 1.2, 0);
lights[0].position.set(0, 0, 0);
lights[1].position.set(1000, 2000, 1000);
lights[2].position.set(- 1000, - 2000, - 1000);
this.viewer.scene.scene.add(lights[0]);
this.viewer.scene.scene.add(lights[1]);
this.viewer.scene.scene.add(lights[2]);
const ambientLight = new THREE.AmbientLight(0x404040, 2.0);
ambientLight.position.set(0, 0, 0);
this.viewer.scene.scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xcccccc, 0.5);
dirLight.position.set(0, 0, 0);
this.viewer.scene.scene.add(dirLight);
};
setPointCloudsVisible = (flag) => {
this.viewer.setEDLEnabled(true);
// Using opacity we can still perform measurements
this.viewer.setEDLOpacity(flag ? 1 : 0);
// for(let pointcloud of viewer.scene.pointclouds){
// pointcloud.visible = flag;
// }
}
componentDidMount() {
var width = window.innerWidth;
var height = window.innerHeight;
// initialize Potree viewer
const viewerElem = this.potreeContainerDiv.current
const Potree = window.Potree
console.log(Potree);
this.camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000);
this.viewer = new Potree.Viewer(viewerElem);
this.addLights()
this.viewer.setEDLEnabled(true);
this.viewer.setFOV(60);
this.viewer.setPointBudget(1 * 1000 * 1000);
this.viewer.setClipTask(Potree.ClipTask.SHOW_INSIDE);
this.viewer.loadSettingsFromURL();
this.viewer.setControls(this.viewer.orbitControls)
// console.log({ this.viewer })
this.viewer.loadGUI(() => {
this.viewer.setLanguage('en');
document.getElementById("menu_appearance").next().show();
this.viewer.toggleSidebar();
});
// Load and add point cloud to scene
// let url = "./point_cloud.ply"
let url = "http://dev.xyz.in/3d/entwine_pointcloud/ept.json"
// let url = "./odm_mesh.ply"
this.scene = this.viewer.scene;
Potree.loadPointCloud(url).then(e => {
let pointcloud = e.pointcloud;
let material = pointcloud.material;
material.activeAttributeName = "rgba";
// material.activeAttributeName = "elevation";
// pointcloud.material.elevationRange = [60, 120];
material.minSize = 2;
material.pointSizeType = Potree.PointSizeType.FIXED
this.viewer.scene.addPointCloud(pointcloud);
this.viewer.fitToScreen();
console.log("This is the url", url);
}, e => console.err("ERROR: ", e));
const objLoader = new OBJLoader(this.manager);
const mtlLoader = new MTLLoader(this.manager);
objLoader.crossOrigin = '';
mtlLoader.crossOrigin = '';
mtlLoader.load(`http://dev.xyz.in/3d/119/odm_texturing/odm_textured_model_geo.mtl`, (materials) => {
// let changeMapKd = async () => {
// Object.keys(materials.materialsInfo).map((material, key) => {
// console.log(materials.materialsInfo[material], '++++++++++++++++++++++++++++++++++', key)
// materials.materialsInfo[material].map_kd = `${materials.materialsInfo[material].map_kd}?${this.props.user.sas_token}`
// })
// }
// changeMapKd().then(() => {
console.log(materials)
materials.preload()
objLoader.setMaterials(materials)
objLoader.load(`http://dev.xyz.in/3d/119/odm_texturing/odm_textured_model_geo.obj`, (object) => {
console.log("sfjbdjghdbfksdlnfdkfsm", object)
// this.camera.position.y = -50;
// this.camera.position.z = 10;
var box = new THREE.Box3().setFromObject(object);
box.getCenter(object.position)
object.position.multiplyScalar(-1);
var pivot = new THREE.Group();
this.viewer.scene.scene.add(pivot);
pivot.add(object)
this.setPointCloudsVisible(false);
})
// })
})
}
}

Forcing tooltip position on Amcharts

In short, I would like to force tooltip to be shown always above the hovered point on line series, even if it goes outside chart area. Tooltip is joint for all series. Example can be seen here:
const {useRef, useState} = React;
const CHART_CONTAINER = 'campaign-budget-chart';
const CHART_COLORS = {
value1: '#05a8fa',
value2: '#ed3434',
value3: '#0ec76a',
}
function getRandomNumber(max){
return Math.floor(Math.random() * Math.floor(max))
}
const initialData = [{
timestamp: new Date(2020, 09, 25),
value1: 0,
value2: getRandomNumber(50),
value3: getRandomNumber(250),
},{
timestamp: new Date(2020, 09, 26),
value1: getRandomNumber(100),
value2: getRandomNumber(50),
value3: getRandomNumber(250),
},{
timestamp: new Date(2020, 09, 27),
value1: getRandomNumber(100),
value2: getRandomNumber(50),
value3: getRandomNumber(250),
},
{
timestamp: new Date(2020, 09, 28),
value1: getRandomNumber(100),
value2: getRandomNumber(50),
value3: getRandomNumber(250),
}];
let i = 0;
function BudgetChart() {
const chartRef = useRef(null);
const [data, setData] = useState(initialData);
const [cursor, setCursor] = React.useState({ x: 0, y: 0 });
const [cursorVisible, setCursorVisible] = React.useState(false);
function createSeries(
fieldX,
fieldY,
name,
lineColor,
) {
if (!chartRef.current) return;
console.log('Create series');
// Init series
let series = chartRef.current.series.push(new am4charts.LineSeries());
series.name = name;
series.dataFields.valueY = fieldY;
series.dataFields.dateX = fieldX;
series.strokeWidth = 3;
series.stroke = am4core.color(lineColor);
series.tooltip.pointerOrientation = 'down';
series.tooltip.background.filters.clear(); // remove shadow
series.tooltip.getFillFromObject = false;
series.tooltip.background.fill = am4core.color('#2a2b2e');
series.tooltip.background.stroke = am4core.color('#2a2b2e');
series.tooltip.label.fontSize = 12;
series.tooltip.background.pointerLength = 0;
series.tooltip.dy = -5;
series.tooltipText = '{valueY}';
series.tensionX = 0.8;
series.showOnInit = false;
// Add bullet for optimization
let circleBullet = series.bullets.push(new am4charts.CircleBullet());
circleBullet.circle.radius = 6;
circleBullet.circle.fill = lineColor;
circleBullet.circle.stroke = am4core.color('#fff');
circleBullet.circle.strokeWidth = 3;
circleBullet.propertyFields.disabled = 'optimizationTooltipDisabled';
// Set up tooltip
series.adapter.add("tooltipText", function(ev) {
var text = "[bold]{dateX}[/]\n"
chartRef.current.series.each(function(item) {
text += "[" + item.stroke.hex + "]●[/] " + item.name + ": {" + item.dataFields.valueY + "}\n";
});
return text;
});
// Bullet shadow
let shadow = circleBullet.filters.push(new am4core.DropShadowFilter());
shadow.opacity = 0.1;
}
React.useEffect(() => {
if (!chartRef.current) {
chartRef.current = am4core.create(CHART_CONTAINER, am4charts.XYChart);
chartRef.current.paddingLeft = 0;
// Add date axis
let dateAxis = chartRef.current.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.labels.template.fontSize = 12;
dateAxis.renderer.labels.template.fill = am4core.color(
'rgba(183,186,199,0.8)'
);
dateAxis.renderer.grid.template.strokeOpacity = 0;
// Add value axis
let valueAxis = chartRef.current.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.grid.template.stroke = am4core.color(
'#f0f2fa'
);
valueAxis.renderer.grid.template.strokeOpacity = 1;
valueAxis.renderer.labels.template.fill = am4core.color(
'rgba(183,186,199,0.8)'
);
valueAxis.renderer.labels.template.fontSize = 12;
// Add cursor
chartRef.current.cursor = new am4charts.XYCursor();
chartRef.current.cursor.maxTooltipDistance = -1;
// Add legend
chartRef.current.legend = new am4charts.Legend();
chartRef.current.legend.position = 'bottom';
chartRef.current.legend.contentAlign = 'left';
chartRef.current.legend.paddingTop = 20;
// Disable axis lines
chartRef.current.cursor.lineX.disabled = true;
chartRef.current.cursor.lineY.disabled = true;
// Disable axis tooltips
dateAxis.cursorTooltipEnabled = false;
valueAxis.cursorTooltipEnabled = false;
// Disable zoom
chartRef.current.cursor.behavior = 'none';
chartRef.current.cursor.events.on('cursorpositionchanged', function(ev) {
let xAxis = ev.target.chart.xAxes.getIndex(0);
let yAxis = ev.target.chart.yAxes.getIndex(0);
setCursor({
x: xAxis.toAxisPosition(ev.target.xPosition),
y: yAxis.toAxisPosition(ev.target.yPosition),
});
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Load data into chart
React.useEffect(() => {
console.log('data ', data)
if (chartRef.current) {
chartRef.current.data = data;
Object.keys(data[0]).forEach(key => {
if(key === 'timestamp') return;
createSeries(
'timestamp',
key,
key,
CHART_COLORS[key]
);
})
}
}, [data]);
// Handle component unmounting, dispose chart
React.useEffect(() => {
return () => {
chartRef.current && chartRef.current.dispose();
};
}, []);
function handleRemoveSeries(){
setData(data.map(item => ({timestamp: item.timestamp, value1: item.value1, value2: item.value2})))
}
return (
<>
<button onClick={handleRemoveSeries}>Remove 3rd series</button>
<div
id={CHART_CONTAINER}
style={{
width: '100%',
height: '350px',
marginBottom: '50px',
}}
/>
</>
);
}
ReactDOM.render(<BudgetChart />, document.getElementById('app'));
For all values near the top of the chart, tooltip is trying to squeeze itself inside chart area. According to the docs:
IMPORTANT: in some situations, like having multiple tooltips stacked for multiple series, the "up" and "down" values might be ignored in order to make tooltip overlap algorithm work.
Is there a way to disable the tooltip overlap algorithm work?
As of version 4.10.8 (released after posting the initial question) there is a property ignoreBounds on series tooltip.
More on ignoreBounds on amchart docs

Ionic 3 - remove images from an ion-slides with help of .getActiveIndex()

I have added images from gallery/camera to an ion-slider view.I have an action sheet which gives me an option to add or remove the images from the slider view.Adding is working fine as i am adding that image to array and providing that updated array to the slider.
But for removing an image i need to get the index of the image that is active on the slider and after that i need to remove it.
I m not able to get the active index using this code :
onSlideChanged() {
try{
let currentIndex = this.slides.getActiveIndex();
console.log("Current index is", currentIndex);
}catch(e){
console.log("not able to get the active index");
} }
this also goes into the catch part.
Then i m removing the first element from the array and updating the array for slider.The array size is reduced when i press the delete button from action sheet but all the images in the slider disappears leaving a blank space.
<div *ngIf="field.value" (click)="takePicture(field.name)">
<ion-slides pager="true" style="max-height:500px" (ionSlideDidChange)="onSlideChanged()">
<ion-slide *ngFor="let c of field.value">
<img class="image-attach" [src]="c" draggable="true">
</ion-slide>
</ion-slides>
</div>
<canvas #latlon style="display:none"></canvas>
</div>
code for setting images to the slider
removePicture(name) {
for (let i = 0; i < this.formType.template.secs.length; i++) {
for (let d = 0; d < this.formType.template.secs[i].fields.length; d++) {
if (this.formType.template.secs[i].fields[d].name == name) {
if(this.formType.template.secs[i].fields[d].value.length>1)
{
this.formType.template.secs[i].fields[d].value.splice(this.currentIndex,1);
this.attachedImagesArray.splice(this.currentIndex,1);
console.log(this.formType.template.secs[i].fields[d].value.length);
var arr = this.formType.template.secs[i].fields[d].value;
console.log("^^^^^^^",arr);
this.formType.template.secs[i].fields[d].value = this.formType.template.secs[i].fields[d].value;
}
else{
console.log("*********",this.formType.template.secs[i].fields[d].value);
this.formType.template.secs[i].fields[d].value = "";
}
}
}
}
};
this is the code i m using for removing the images from slider.
I m new to ionic so don't know why this is happening, i googled for it but nothing worked for me.
for putting the images to the slides i m using the following code :
selecPicture(name) {
this.camera.getPicture({
quality: 50,
destinationType: this.camera.DestinationType.FILE_URI,
targetHeight: 500,
targetWidth: 500,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}).then((imageData) => {
//alert(imageData);
// imageData is a base64 encoded string DATA_URL FILE_URI 'lat: '+lat+', lon: '+lon,
let base64Image = "data:image/jpeg;base64," + imageData;
this.geolocation.getCurrentPosition().then((resp) => {
let lat = resp.coords.latitude;
let lon = resp.coords.longitude;
this.lat = lat;
this.lon = lon;
let d = new Date();
let draftSavedTime = d.toString().substr(4, 11);
let canvas = this.canvasRef.nativeElement;
let context = canvas.getContext('2d');
console.log(context);
console.log("hello");
let newImg = new Image();
newImg.src = imageData;
newImg.onload = () => {
canvas.setAttribute("width", newImg.height);
canvas.setAttribute("height", newImg.width);
// context.drawImage(newImg, 0, 0);
context.drawImage(newImg, 0, 0, newImg.width, newImg.height);
// context.font = "15px impact";
context.font = "bold 13px Arial";
// context.textAlign = 'center';
context.fillStyle = 'red';
context.fillText(draftSavedTime, 20, 20);
// context.fillText('Lat: '+lat+' Lon: '+lon, canvas.width / 2, canvas.height * 0.9);
context.fillText('Lat: ' + lat, canvas.width * 0.1, canvas.height * 0.8);
context.fillText('Lon: ' + lon, canvas.width * 0.1, canvas.height * 0.9);
// context.fillText('Lon: '+lon, canvas.width / 2, canvas.height * 0.8);
let image = canvas.toDataURL();
this.attachedImages.push(image);
this.setValue(name, image);
};
}).catch((error) => {
console.log('Error getting location', error);
});
}, (err) => {
console.log(err);
});
}
to set the value of image in the field :
//to set the value in the field
setValue(name, data) {
console.log(this.attachedImages);
console.log(this.formType.template.secs); //3
for (let i = 0; i < this.formType.template.secs.length; i++) {
console.log(this.formType.template.secs[i].fields); //2
for (let d = 0; d < this.formType.template.secs[i].fields.length; d++) {
if (this.formType.template.secs[i].fields[d].name == name) {
this.attachedImagesArray.push({
name : this.formType.template.secs[i].fields[d].name,
image : data,
number : d
});
var group_to_values = this.attachedImagesArray.reduce(function (obj, item) {
obj[item.name] = obj[item.name] || [];
obj[item.name].push(item.image);
return obj;
}, {});
var imageGroup = Object.keys(group_to_values).map(function (key) {
return {key: key, image: group_to_values[key]};
});
var pre = document.createElement("pre");
pre.innerHTML = "imageGroup:\n\n" + JSON.stringify(imageGroup, null, 4);
document.body.appendChild(pre);
var newArr = [];
newArr.push({imageGroup});
for(var item in newArr)
{
console.log(newArr[item]);
for(var sec in newArr[item])
{
console.log(newArr[item][sec]);
}
for( var elm in newArr[item][sec])
{
console.log(newArr[item][sec][elm]);
}
for( var key in newArr[item][sec][elm])
{
this.arrNameStr = newArr[item][sec][elm].key;
console.log(newArr[item][sec][elm].image);
}
}
console.log(this.arrNameStr);
if(this.arrNameStr.includes(this.formType.template.secs[i].fields[d].name))
{
console.log(newArr[item][sec][elm].image);
console.log(this.formType.template.secs[i].fields[d].value);
this.formType.template.secs[i].fields[d].value = newArr[item][sec][elm].image;
console.log(this.formType.template.secs[i].fields[d].value);
}
}
}
}
};
First ensure that you get this event firing off and that your reference to the slides element in the template returns the Slides: (ionSlideDidChange). Do:
onSlideChanged() {
console.log(this.slides)
}
Your console should return reference to the slides element.
It is unclear how you obtain this reference based on your code, but seeing you have *ngIf directive there is a chance you are not actually able to get it since the element doesn't exist at init stage of the component.
To fix that you can pass reference to ion-slides in the ionSlidesChanged method:
<div *ngIf="field.value" (click)="takePicture(field.name)">
<ion-slides #mySlides (ionSlideDidChange)="onSlideChanged(mySlides); mySlides.update()" pager="true" style="max-height:500px">
<ion-slide *ngFor="let c of field.value">
<img class="image-attach" [src]="c" draggable="true">
</ion-slide>
</ion-slides>
</div>
Now in the actual method you should be able to get the value of currentIndex:
onSlideChanged(mySlides) {
let currentIndex = mySlides..getActiveIndex();
// here do splice or whatever manipulation you need with your data source / array
}
Let me know if this helped.
UPDATE: since there is a need to refresh slides UI after the change to the model it is good to call "update" method: (ionSlideDidChange)="onSlideChanged(mySlides); mySlides.update()".
Template is now updated with this.

Spring between two draggable surfaces in famo.us

I'm trying to implement two surfaces, connected with a spring, that would react to drag in famo.us. So far I have setup the surfaces, can drag those, have a spring that interacts during the loading of the page, but not on drag. So the questions are a) how should I connect two surfaces with a spring and b) how do I update the physics when I drag one surface so that the other surface would follow the dragged surface?
The code I so far have is this
define(function(require) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var StateModifier = require('famous/modifiers/StateModifier');
var PhysicsEngine = require('famous/physics/PhysicsEngine');
var Circle = require('famous/physics/bodies/Circle');
var Draggable = require('famous/modifiers/Draggable');
var Spring = require('famous/physics/forces/Spring');
var Vector = require('famous/math/Vector');
var context = Engine.createContext();
var physicsEngine = new PhysicsEngine();
var ball = new Surface ({
size: [100,100],
properties: {
backgroundColor: 'red',
borderRadius: '50px'
}
});
var ball2 = new Surface ({
size: [100,100],
properties: {
backgroundColor: 'blue',
borderRadius: '50px'
}
});
var draggable = new Draggable();
var draggable2 = new Draggable();
ball.state = new StateModifier({origin:[0.2,0.2]});
ball2.state = new StateModifier({origin:[0.3,0.3]});
ball.particle = new Circle({radius:100});
ball2.particle = new Circle({radius:100});
var spring = new Spring({
anchor: ball.particle,
period: 400, // <= Play with these values :-)
dampingRatio: 0.07, // <=
length: 50
});
// var spring2 = new Spring({anchor: ball2.particle});
// physicsEngine.attach(spring, ball2.particle);
// physicsEngine.attach(spring2, ball.particle);
draggable.subscribe(ball);
draggable2.subscribe(ball2);
draggable.on('update', function() {
console.info('update');
ball2.particle.applyForce(new Vector(0, 0, -0.005 * 100));
// ball.state.setTransform(ball.particle.getTransform())
// ball.state.setTransform(ball.particle.getTransform())
// ball.particle.setVelocity([0.001,0,0]);
// physicsEngine.wake();
// physicsEngine.step();
});
draggable2.on('update', function() {
// ball2.particle.setVelocity([0.001,0,0]);
// console.info('update');
// physicsEngine.wake();
// physicsEngine.step();
});
physicsEngine.attach(spring, ball2.particle);
// spring.applyForce(ball.particle);
physicsEngine.addBody(ball.particle);
physicsEngine.addBody(ball2.particle);
// ball.on("click",function(){
// ball.particle.setVelocity([10,0,0]);
// });
//
// ball2.on("click",function(){
// ball2.particle.setVelocity([0,10,0]);
// });
context.add(draggable).add(ball.state).add(ball);
context.add(draggable2).add(ball2.state).add(ball2);
Engine.on('prerender', function(){
ball.state.setTransform(ball.particle.getTransform());
ball2.state.setTransform(ball2.particle.getTransform());
});
});
It seems like you have a pretty good understanding of the PE thus far. I can still see a few places you can improve. Here is a working example of dragging with a spring attached. Although this implementation is not perfect yet, it should get you started.. If you start with dragging the red circle, everything works as expected.. Draggable has its own position, and so does particle. So when you grab the blue circle, there remains an offset in particle. Here is what will get you 95%..
Hope it helps..
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Modifier = require('famous/core/Modifier');
var Draggable = require('famous/modifiers/Draggable');
var PhysicsEngine = require('famous/physics/PhysicsEngine');
var Circle = require('famous/physics/bodies/Circle');
var Spring = require('famous/physics/forces/Spring');
var context = Engine.createContext();
var physicsEngine = new PhysicsEngine();
var ball = new Surface ({
size: [100,100],
properties: {
backgroundColor: 'red',
borderRadius: '50px'
}
});
var ball2 = new Surface ({
size: [100,100],
properties: {
backgroundColor: 'blue',
borderRadius: '50px',
}
});
ball.mod = new Modifier({origin:[0.5,0.5]});
ball.draggable = new Draggable();
ball.pipe(ball.draggable);
ball.particle = new Circle({radius:100});
ball.mod.transformFrom(function(){ return Transform.translate(0,0,0) });
ball.spring = new Spring({
anchor: ball.particle,
period: 400,
dampingRatio: 0.07,
length: 50
});
ball2.mod = new Modifier({origin:[0.5,0.5]});
ball2.draggable = new Draggable();
ball2.pipe(ball2.draggable);
ball2.particle = new Circle({radius:100});
ball2.mod.transformFrom(function(){ return ball2.particle.getTransform()});
ball2.spring = new Spring({
anchor: ball2.particle,
period: 400,
dampingRatio: 0.07,
length: 50
});
ball.draggable.on('start',function(){
ball2.setProperties({pointerEvents:'none'});
if (ball2.springID) physicsEngine.detach(ball2.springID);
if (ball.springID) physicsEngine.detach(ball.springID);
ball.springID = physicsEngine.attach(ball.spring, ball2.particle);
ball2.springID = null;
ball.mod.transformFrom(function(){ return Transform.translate(0,0,0) });
ball2.mod.transformFrom(function(){ return ball2.particle.getTransform()});
})
ball.draggable.on('update', function() {
pos = ball.draggable.getPosition();
ball.particle.setPosition(pos);
});
ball.draggable.on('end', function() {
ball2.setProperties({pointerEvents:'all'});
});
ball2.draggable.on('start',function(){
ball.setProperties({pointerEvents:'none'});
if (ball2.springID) physicsEngine.detach(ball2.springID);
if (ball.springID) physicsEngine.detach(ball.springID);
ball2.springID = physicsEngine.attach(ball2.spring, ball.particle);
ball.springID = null;
ball2.mod.transformFrom(function(){ return Transform.translate(0,0,0) });
ball.mod.transformFrom(function(){ return ball.particle.getTransform()});
})
ball2.draggable.on('update', function() {
pos = ball2.draggable.getPosition();
ball2.particle.setPosition(pos);
});
ball2.draggable.on('end', function() {
ball.setProperties({pointerEvents:'all'});
});
ball.springID = physicsEngine.attach(ball.spring, ball2.particle);
physicsEngine.addBody(ball.particle);
physicsEngine.addBody(ball2.particle);
context.add(ball.mod).add(ball.draggable).add(ball);
context.add(ball2.mod).add(ball2.draggable).add(ball2);

Categories

Resources