Multiple Button to Open Associated Image of Photoswipe - javascript

Supposed we have 2 images. Using Photoswipe js below, i will have second button beside 'btn', so that when clicking the other button, it will directly open second image at first, instead of the first image.
So we will do this :
document.getElementById('btn').onclick = openPhotoSwipe(do..something..);
document.getElementById('btn2').onclick = openPhotoSwipe(do..something..);
Please help!
var openPhotoSwipe = function() {
var pswpElement = document.querySelectorAll('.pswp')[0];
// build items array
var items = [
{
src: 'https://farm2.staticflickr.com/1043/5186867718_06b2e9e551_b.jpg',
w: 964,
h: 1024
},
{
src: 'https://farm7.staticflickr.com/6175/6176698785_7dee72237e_b.jpg',
w: 1024,
h: 683
}
];
// define options (if needed)
var options = {
// history & focus options are disabled on CodePen
history: false,
focus: false,
showAnimationDuration: 0,
hideAnimationDuration: 0
};
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
openPhotoSwipe();
document.getElementById('btn').onclick = openPhotoSwipe;

You need to use PhotoSwipe API
Here is a working fiddle
var pswpElement = document.querySelectorAll('.pswp')[0];
var items = [{
src: 'https://placekitten.com/600/400',
w: 600,
h: 400
},
{
src: 'https://placekitten.com/1200/900',
w: 1200,
h: 900
}
];
var options = {
index: 0
};
//var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
//gallery.init();
var x = document.querySelectorAll(".opengallery");
for (let i = 0; i < x.length; i++) {
x[i].addEventListener("click", function() {
opengallery(x[i].dataset.image);
});
}
function opengallery(j) {
options.index = parseInt(j);
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
}

Related

error code in console after using destroy function from chart.js

let myChart = null;
function draw(){
const labels = [];
for (var i = 0; i < stats.length; i++) {
labels.push(legend[i]);
}
const data = {
labels: labels,
datasets: [{
backgroundColor: ['rgb(204,0,0)', 'rgb(241,194,50)', 'rgb(41,134,204)', 'rgb(106,168,79)', 'rgb(255,62,153)'],
data: stats,
}]
};
const config = {
type: 'doughnut',
data: data,
options: {
radius: 200,
hoverOffset: 30,
aspectRatio: 1,
maintainAspectRatio: false,
responsive: false,
}
};
if (myChart !== null) {
myChart.destroy();
}
myChart = new Chart(document.getElementById('defaultCanvas0'), config);
}
When i run this code my chart just keeps flickering and drawing itself over and over again with a new id each time. I need to be able to destroy my original chart before drawing a new one
This is what console.log displays:
Edit:
function HealthStudy() {
//name for the visualisation to appear in the menu bar
this.name = "Health study";
//each visualisation must have a unique ID with no special characters
this.id = "Health-study";
//property to represent whether stats has been loaded
this.loaded = false;
// Preload the stats. This function is called automatically by the
// gallery when a visualisation is added.
this.preload = function () {
var self = this;
this.stats = loadTable(
'./data/health/causes-of-death.csv', 'csv', 'header',
// Callback function to set the value
// this.loaded to true.
function (table) {
self.loaded = true;
});
};
this.setup = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Create a select DOM element.
this.select = createSelect();
this.select.position(800, 380);
// Fill the options with all country names.
var countries = this.stats.columns;
// First entry is empty.
for (let i = 1; i < countries.length; i++) {
this.select.option(countries[i]);
}
};
this.destroy = function () {
this.select.remove();
};
// Create a new donut object.
this.donut = new Donut(width / 2, height / 2, width * 0.4);
this.draw = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Get the value of the country we're interested in from the
// select item.
var country = this.select.value();
// Get the column of raw stats for country.
var col = this.stats.getColumn(country);
// Convert all stats strings to numbers.
col = stringsToNumbers(col);
// Copy the row labels from the table (the first item of each row).
var legend = this.stats.getColumn(0);
// Colour to use for each category.
var colours = ['#CC0000', '#55a5f2', '#4dff00', '#f4e410', '#6a329f'];
// Make a title.
var title = 'Top 5 causes of death in ' + country;
// Draw the Donut!
this.donut.draw(col, legend, colours, title);

how to crop same image multiple times with konva.image

i am trying to get cells from a photo with a table. i have the coordonates of the cells in the image. now i want to view my cells using a konvajs library. the problem is that the table is 30x30. so i have 900 cells. when using kanva.image 900 times the browser stop working, because it tries to load 900 time the same image. i want to load one time the image and use it for croping 900 time. here are my code:
function add_i(layer,cell,row,weight,k,cloneI){
layer.add(cloneI);
cloneI.crop({
x: parseInt(cell.x),
y: parseInt(row.y),
width: cell.width,
height: row.height
});
cloneI.width(cell.width);
cloneI.height(row.height);
cloneI.y(row.y);
cloneI.x(cell.x);
}
layerP.push( new Konva.Layer());
if(weight.stage == 'pred'){
var cloneI = new Konva.Image({
id:'img_'+k,
draggable: true
});
var clone = new Image();
clone.onload = function() {
cloneI.image(clone);
layerP[0].draw();
};
for (var i in weight.predictions){
var row = weight.predictions[i];
for (var j in row.cells){
var cell = row.cells[j];
add_i(layerP[0],cell,row,weight,k,cloneI.clone());
k+=1;
}
if(i==4 && false)
break;
}
clone.src = weight.path_i;
stage.add(layerP[0]);
}
I think you should move your add_i into clone.onload like this:
function add_i(layer, cell, row, weight, k, cloneI) {
layer.add(cloneI);
cloneI.crop({
x: parseInt(cell.x),
y: parseInt(row.y),
width: cell.width,
height: row.height
});
cloneI.width(cell.width);
cloneI.height(row.height);
cloneI.y(row.y);
cloneI.x(cell.x);
}
layerP.push(new Konva.Layer());
if (weight.stage == 'pred') {
var clone = new Image();
clone.onload = function() {
var cloneI = new Konva.Image({
id: 'img_' + k,
draggable: true,
image: clone
});
for (var i in weight.predictions) {
var row = weight.predictions[i];
for (var j in row.cells) {
var cell = row.cells[j];
add_i(layerP[0], cell, row, weight, k, cloneI.clone());
k += 1;
}
if (i == 4 && false)
break;
}
layerP[0].draw();
};
clone.src = weight.path_i;
stage.add(layerP[0]);
}
cause the add_i is invoked before the onload callback because of that Konva.Image i.e. cloneI does not have native image instance when it's used.

JavaScript, Trying to get buttons to move on click

/*
var young_link = {
power: 30,
cpower: 20,
hp: 3,
image: "../images/young_link.jpg",
};
var young_zelda = {
power: 30,
cpower: 20,
hp: 3,
}
var impa = {
power: 30,
cpower: 20,
hp: 3,
}
var hey = {
power: 30,
cpower: 20,
hp: 3,
}
//$("#test").html(young_link);
console.log(young_link);*/
$(document).ready(function() {
var hero_image = new Array();
hero_image[0] = new Image();
hero_image[0].src = 'assets/images/link.png';
hero_image[0].id = 'image';
hero_image[1] = new Image();
hero_image[1].src = 'assets/images/bongo.png';
hero_image[1].id = 'image';
hero_image[2] = new Image();
hero_image[2].src = 'assets/images/gandondorf.jpg';
hero_image[2].id = 'image';
hero_image[3] = new Image();
hero_image[3].src = 'assets/images/queen.png';
hero_image[3].id = 'image';
//var test = "<img src= '../images/young_link.jpg'>";
//var young_hero = ["young_link","young_zelda","impa", "malon"];
var young_hero = ["Link", "Bongo Bongo","Gandondorf","Queen Gohma"];
var health = [100, 70, 120, 50];
for (var i = 0; i < young_hero.length; i++) {
var hero_btns = $("<buttons>");
hero_btns.addClass("hero hero_button");
hero_btns.attr({"data-name":young_hero[i],"data-health":health[i],"data-image":hero_image[i]});
hero_btns.text(young_hero[i]);
hero_btns.append(hero_image[i]);
hero_btns.append(health[i]);
$("#buttons").append(hero_btns);
}
$(".hero_button").on("click" , function() {
var battle_ground = $("<div>");
battle_ground.addClass("hero hero_button");
battle_ground.text($(this).data("data-name"));
$("#battle").append(battle_ground);
});
});
The for loop is working and appending the buttons on the screen. But in $(".hero_button").on("click" , function() it is just putting a empty box on the page with a click. So, it is not taking the data that is attached to the button.
Sam answered your question correctly and rightly deserves the accepted answer. But I wanted to give you an insight into how you can do this in a cleaner way, without lots of arrays which must line up. Also without using jQuery at all. Below you can see a more object oriented way to do this.
You can see it in action in this jsFiddle
// Now we have an object which represents a hero. No need to duplicate loads of code.
function Hero(heroData) {
this.name = heroData.name;
this.health = heroData.health;
this.setImage = function() {
this.image = new Image();
this.image.src = heroData.imageSrc;
this.image.id = heroData.imageId;
}
this.createHeroButton = function() {
this.createButtonElement();
this.addButtonToPage();
this.attachButtonEvents();
}
this.createButtonElement = function() {
var heroButton = document.createElement('button');
heroButton.classList.add('hero,hero_button');
heroButton.setAttribute('name', this.name);
heroButton.setAttribute('health', this.health);
heroButton.appendChild(this.image);
this.button = heroButton;
}
this.attachButtonEvents = function() {
this.button.addEventListener('click', this.addButtonToPage.bind(this));
}
this.addButtonToPage = function() {
var container = document.getElementById('container');
container.appendChild(this.button);
}
this.takeDamage = function(damageValue) {
this.health -= damageValue;
this.button.setAttribute('health', this.health);
}
this.setImage();
}
// So here we create a Hero instance, in this case Link, we can use now describe links attributes, image, name, health...
var link = new Hero({
name: 'Link',
health: 100,
imageSrc: 'http://orig12.deviantart.net/8bb7/f/2011/276/4/e/four_swords_link_avatar_by_the_missinglink-d4bq8qn.png',
imageId: 'link-image'
});
var mario = new Hero({
name: 'Mario',
health: 100,
imageSrc: 'http://rs568.pbsrc.com/albums/ss123/stvan000/thumb-super-mario-bros-8bit-Mario.jpg~c200',
imageId: 'mario-image'
});
// Now we can easily make a button and add it to the page
link.createHeroButton();
mario.createHeroButton();
// Lets try decreasing the health on mario
mario.takeDamage(10);
// Because we have an object reference which handles all of our heros state we can decrease his health and update the buttons data without much trouble.
A couple of changes to get the data set and read correctly:
make button tags instead of buttons
use .attr() instead of .data() to get the attributes
See comments inline in the code below.
Also, instead of adding an attribute for the Image object of each item (which will add an attribute like data-image="[Object object]") just add an integer corresponding to the iterator index and use that to reference into the hero_image array when you need to get the corresponding image.
Additionally, you can use Array.forEach() to iterate over the items in the heroes array with a callback function. That way you don't have to worry about updating the iterator variable (i in this case) and indexing into the array. You should take a look at this functional programming guide which has some good exercises.
$(document).ready(function() {
var hero_image = new Array();
hero_image[0] = new Image();
hero_image[0].src = 'assets/images/link.png';
hero_image[0].id = 'image';
hero_image[1] = new Image();
hero_image[1].src = 'assets/images/bongo.png';
hero_image[1].id = 'image';
hero_image[2] = new Image();
hero_image[2].src = 'assets/images/gandondorf.jpg';
hero_image[2].id = 'image';
hero_image[3] = new Image();
hero_image[3].src = 'assets/images/queen.png';
hero_image[3].id = 'image';
var young_heroes = ["Link", "Bongo Bongo", "Gandondorf", "Queen Gohma"];
var health = [100, 70, 120, 50];
young_heroes.forEach(function(young_hero,i) {
var hero_btns = $("<button>");
hero_btns.addClass("hero hero_button");
hero_btns.attr({
"data-name": young_hero,
"data-health": health[i],
//instead of adding an attribute for the image object, just add an index
"data-index": i
});
hero_btns.text(young_hero);
hero_btns.append(hero_image[i]);
hero_btns.append(health[i]);
$("#buttons").append(hero_btns);
});
$(".hero_button").on("click", function() {
var battle_ground = $("<div>");
battle_ground.addClass("hero hero_button");
//use .attr() here instead of .data()
battle_ground.text($(this).attr("data-name"));
/** My additions -
* I am not sure exactly how this should be done
* so adjust accordingly
**/
//additionally, you can add attributes to the new battle_ground item
battle_ground.attr('data-health',$(this).attr("data-health"));
battle_ground.append(hero_image[$(this).attr("data-index")]);
battle_ground.append($(this).attr("data-health"));
/** End my additions **/
$("#battle").append(battle_ground);
});
});
#battle div {
border: 1px solid #555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="buttons"></div>
Battle ground:
<div id="battle"></div>

Maximum call stack size exceeded in custom Image filter

I am looking for a way to fill an Image with an image pattern in a FabricJs canvas, since there is not a built-in image filter to do this. Although my code is still in an early version, basically it should work(unfortunately it doesn't);
All the eavy work is done by applyTo method, where I load an image, then fill an hidden canvas with a pattern. I noticed that there is a function (source) which fall in an infinite recursion:
var pattern = new fabric.Pattern({
source: function () {
fhc.setDimensions({
width: smile.getWidth() + 5,
height: smile.getHeight() + 5,
});
return fhc.getElement();
},
repeat: 'repeat'
});
I have prepared a demo on JSFiddle
Could anyone help me to understand how to solve this issue?
(function (global) {
'use strict';
var fabric = global.fabric || (global.fabric = {}),
extend = fabric.util.object.extend;
fabric.Image.filters.ImagePatternEffect = fabric.util.createClass(fabric.Image.filters.BaseFilter, {
type: 'ImagePatternEffect',
initialize: function (options) {
options = options || {};
this.img = options.img;
},
applyTo: function (canvasEl) {
var w = canvasEl.width;
var h = canvasEl.height;
var hc = document.createElement('canvas');
fabric.Image.fromURL('http://i.imgur.com/0Ks0mlY.png', function (smile) {
debugger;
hc.setAttribute('width', w);
hc.setAttribute('height', h);
var fhc = new fabric.StaticCanvas(hc);
fhc.add(smile);
var pattern = new fabric.Pattern({
source: function () {
fhc.setDimensions({
width: smile.getWidth() + 5,
height: smile.getHeight() + 5,
});
return fhc.getElement();
},
repeat: 'repeat'
});
var rect = new fabric.Rect({
fill: pattern,
width: w,
height: h
});
fhc.add(rect);
fhc.renderAll();
var ifhcContext = fhc.getContext('2d');
var fhcImageData = ifhcContext.getImageData(0, 0, fhc.width, fhc.height);
var fhcData = fhcImageData.data;
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data;
for (var i = 0, n = data.length; i < n; i += 4) {
data[i] += fhcData[i];
data[i + 1] += fhcData[i + 1];
data[i + 2] += fhcData[i + 2];
}
context.putImageData(imageData, 0, 0);
});
},
toObject: function () {
return extend(this.callSuper('toObject'), {
});
}
});
fabric.Image.filters.ImagePatternEffect.fromObject = function (object) {
return new fabric.Image.filters.ImagePatternEffect(object);
};
})(typeof exports !== 'undefined' ? exports : this);
var canvas = new fabric.Canvas('c');
fabric.Image.fromURL('http://i.imgur.com/qaQ8jir.png', function (img) {
var orImg = img;
img.filters.push(new fabric.Image.filters.ImagePatternEffect({
img: orImg,
}));
img.applyFilters(canvas.renderAll.bind(canvas));
canvas.add(img.set({
width: 300,
height: 300,
}));
}, {
crossOrigin: ''
});
i also use pattern image on my web application , in order to add it on objects, and it works.
All you need is this function function loadPattern(url, seatObj) where i pass the object which i want to add the pattern each time and the image(pattern) link.
here is the snippet :
function loadPattern(url, seatObj) {
//i use the loadImage function to load the image and pass it to the fabric.Pattern constructor
fabric.util.loadImage(url, function (img) {
//i change the fill property of the object to the
//image that i want to load on it as a pattern
seatObj.fill = new fabric.Pattern({
source: img,
repeat: 'no-repeat'
});
//refresh canvas and watch your image pattern on the object
canvas.renderAll();
});
}
hope this helps,
good luck

Can't create more than one overlay in Seadragon

I am trying to add overlays to a seadragon map I am making but for some reason that I can not figure our seadragon ignores all my overlays except the first one. Any help with this is much appreciated.
var viewer = null;
function init() {
Seadragon.Config.autoHideControls = false;
viewer = new Seadragon.Viewer("container");
viewer.addEventListener("open", addOverlays);
viewer.addControl(makeControl(), Seadragon.ControlAnchor.TOP_RIGHT);
$(viewer.getNavControl()).parent().parent().css({ 'top': 10, 'right': 10 });
viewer.openDzi("_assets/Mapdata/dzc_output.xml");
}
function makeControl() {
var control = document.createElement("a");
var controlText = document.createTextNode("");
control.href = "#"; // so browser shows it as link
control.className = "control";
control.appendChild(controlText);
Seadragon.Utils.addEvent(control, "click",
onControlClick);
return control;
}
function onControlClick(event) {
Seadragon.Utils.cancelEvent(event); // don't process link
if (!viewer.isOpen()) {
return;
}
// These are the coordinates of europe on this map
var x = 0.5398693914203284;
var y = 0.21155952391206562;
var z = 5;
viewer.viewport.panTo(new Seadragon.Point(x, y));
viewer.viewport.zoomTo(z);
viewer.viewport.ensureVisible();
}
function addOverlays(viewer) {
drawer = viewer.drawer;
var img = document.createElement("img");
img.src = "_assets/Images/pushpin.png";
$(img).addClass('pushPin');
var overlays = [
{ elmt: img, point: new Seadragon.Point(0.51, 0.22) },
{ elmt: img, point: new Seadragon.Point(0.20, 0.13) }
];
for (var i = 0; i < overlays.length; i++) {
drawer.addOverlay(overlays[i].elmt, overlays[i].point);
}
}
Seadragon.Utils.addEvent(window, "load", init);
I should have created a function that returns the img and call that inside the object array
function newpushPin() {
var img = document.createElement("img");
img.src = "_assets/Images/pushpin.png";
return img
}
var overlays = [
{ elmt: newpushPin(), point: new Seadragon.Point(0.51, 0.22) },
{ elmt: newpushPin(), point: new Seadragon.Point(0.53, 0.22) },
{ elmt: newpushPin(), point: new Seadragon.Point(0.53, 0.23) },
{ elmt: newpushPin(), point: new Seadragon.Point(0.50, 0.20) }
];

Categories

Resources