How to disable dataTransfer onDrag in a react component? - javascript

I have an draggable div in a react app. When I enable dragging by using draggable={true}, I see a ghost image is created and it follows the mouse movement. I just wanted to get rid of it.
My actual component is the first one. The ghost image is the second one.
When I looked up for it, I found this stackoverflow solution. Implemented the following code snippet, and it cleared the old ghost.
let img = new Image();
img.src = empty; // this is just an empty png file
const onDragStartHandler = (event) => {
event.dataTransfer.setDragImage(img,0,0)
// ...
}
However, now I see a different animation for a fraction of a second at the very beginning of the drag operation. How can I remove that? Or is there a way to completely disable the dataTrasfer? Tried event.dataTransfer.clearData() but it did not worked out.

Related

React - Dragging a file drags text/plain instead

I'm working on an Image Uploader that allows the user to drag and drop images. It works some of the time, but once in a few it just decides not to work. I checked the e.dataTransfer of the drag and drop events, and when it doesn't work, the types array is either empty or has text/plain instead of Files, and the files is empty.
I assumed this might be because of where I grab the file when I start dragging it, but there doesn't seem to be a difference - sometimes it works and sometimes it just doesn't. Also, seems to me like there has to be some way to ensure that it works...
Tried screwing around with the dataTransfer.effectAllowed and dataTransfer.dropEffect to no avail...
Here is my Drag Event handler
(onDragEnter, onDragOver, onDragLeave)
const handleDrag = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
// some stuff to set styling of the component
}
And my drop handler:
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
// more styling stuff
// temporary warning I have displayed so I can see when it doesn't work more easily
if (!e.dataTransfer.types.includes("Files") setError();
// handles the displaying of the image
if (e.dataTransfer.files && e.dataTransfer.files[0]) onFileDrop(e.dataTransfer.files[0]);
}
I checked, and when it doesn't work, the path to the image - like file:///home/USERNAME/Pictures/fantastic_mr_fox_2.jpg... I tried to simply display the image at that path but got an error message that reads Not allowed to load local resource.
Is there any way to either prevent the path from being the dragged item or to use that path and display the image?
Would highly appreciate help!

change default cursor style in PIXI.js

I want to change my cursor when triggering a mousedown event. I found a lot of hints how to achieve that - but these have one major issue. To change the defaultCursorStyle property I need to instantiate the InteractionManager prototype.
var renderer = PIXI.autoDetectRenderer(640, 480),
var interactionManager = new PIXI.interaction.InteractionManager(renderer)
interactionManager.defaultCursorStyle = "crosshair" // a native html/css cursor style
That looks fine at first but the problem here is that this InteractionManager seems to batch-register all events applied to PIXI object via the .on(event, callback) event-binding function per instance.
That means that if there would be a second instance of this InteractionManager, all events would be bound twice and therefore triggered twice. I had this exact issue.
So I needed to revert my changes and try to access the default InteractionManager. Somebody in the HTML5GameDev forum told me to access it like this:
renderer.plugins.interaction
knowing that I tried the following:
renderer.plugins.interaction.defaultCursorStyle = "crosshair"
My events now worked properly again. But the cursor change did not happen. However debugging the line told me that the property defaultCursorStyle was successfully set to "crosshair". Now I'm looking for a way to make this change visible.
My question:
Is there a better way to change the cursor style than the mentioned one above? If no, how can I make my default cursor change visible after setting the new style to the default InteractionManager?
There's a setCursorMode method in the docs, guess it's what you need.
const app = new PIXI.Application({ height, width })
app.renderer.plugins.interaction.cursorStyles.default = 'crosshair'
setTimeout(() => {
app.renderer.plugins.interaction.setCursorMode('pointer')
}, 1000)
Whenever cursor leaves the renderer, PIXI resets cursor mode (here's exactly the line). So you might want to set new cursor mode as default each time you change it.
function changeCursorMode (cursorMode) {
app.renderer.plugins.interaction.cursorStyles.default = cursorMode
app.renderer.plugins.interaction.setCursorMode(cursorMode)
}
app.renderer.plugins.interaction.cursorStyles.crosshair = 'crosshair'
changeCursorMode('crosshair')

How to Manipulate Image After Uploaded To Canvas (FabricJS)

I've been racking my brain on this for a while now, but I can't seem to rotate the image on Canvas after uploading. Here's the code sample in question:
// INITIATE & DRAW CANVAS
var canvas = new fabric.Canvas('CanvasArtArtboard');
// CREATE OVERLAY GRIDS
canvas.setOverlayColor('rgba(205, 173, 64, 0.6)', canvas.renderAll.bind(canvas));
// UPLOAD USER IMAGE TO CANVAS
document.getElementById('imgLoader').onchange = function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var imgObj = new Image();
imgObj.src = event.target.result;
imgObj.onload = function () {
// start fabricJS stuff
var image = new fabric.Image(imgObj);
image.set({
originX: 'left',
originY: 'top',
padding: 0,
cornersize: 10,
scaleX: 0.4,
scaleY: 0.4,
});
//image.scale(getRandomNum(0.1, 0.25)).setCoords();
canvas.add(image);
image.sendToBack();
canvas.renderAll();
//end fabricJS stuff
}
}
reader.readAsDataURL(e.target.files[0]);
}
// ROTATE UPLOADED IMAGE
$("#angle-control").click(function(){
var curAngle = canvas.item(0).getAngle();
canvas.item(0).setAngle(curAngle+15);
canvas.renderAll();
});
I've looked at the following example:
Add image from user computer to canvas (Stack OverFlow Question)
http://jsfiddle.net/PromInc/3efe2x9j/
Once the user uploads their image and clicks the "rotate 90*" button, I'm looking for the image to then rotate.
EDIT: Apologies, here is my JSFiddle in it's current state: http://jsfiddle.net/darnellcreates/oq6htzew/3/
I had a look at your fiddle and there is a lot wrong. The code for rotating is ok (sort of) but the page is full of problems.
First there is no JQuery and you are using the JQuery $ function as selector to access DOM elements. I do not see the point in using jQuery if all you are doing is using it as a selector, you use document.getElementById in some parts and $ in others. This totally negates any benefit Jquery would provide.
Second you are duplicating DOM element ID's (This is a strict no no) DOM ID's must be unique to the page.
To get you on your way here are a few changes,
Change the slider element in the HTML to
<input type="range" id="angleControl1" value="0" min="-90" max="90">
Note that the id is unique to the page. I have also avoided the naming convention (did not make it angle-control1) as this is a simple page and I will take some shortcuts and access the DOM elements directly in JavaScript.
Next remove the click handler for the range slider and replace it with a mouse move event listener.
// keep a copy of the last value so there is no needless rotates
var lastValue = angleControl1.value; // no need to search the node tree.
// you can access elements directly by
// their ID.
// Listen to the mousemoves of the range control. Click, change will
// only update at the end of the mouse down up process. This does not
// provide good user feedback
angleControl1.addEventListener("mousemove",function(){
if(this.value !== lastValue){ // only update the angle if it has changed
// set the angle to the absolute angle rather than relative as you had it
canvas.item(0).setAngle(Number(this.value)); // Number() is me being pedantic
canvas.renderAll(); // rerender
lastValue = this.value; // remember the last value
}
}); // all done for this function
Note. Direct DOM element access can be problematic in some situations (if you duplicate ID's, use that id as a variable before the DOM has loaded, your page is sharing the global namespace, or someone is using an old netscape browser) but for simple pages it is the easiest and safest way (If someone has netscape they can't run the page anyway because there is not canvas element).
Also remove the other Jquery calls $() as they cause the page to crash and stop everything from running.
You need to use the DevTools in these types of situations. It will show you all the errors and give you warnings (FireFox) for bad habits. To access the DevTool hit f12 on most browsers.The DevTools console will list errors and provide a link directly to the code where it is happening. You can also step through the code line by line so you can see what is going on.
i updated your jsfiddle ,to work both the rotate button 90o and the range bar,
just in case you need it.
link: http://jsfiddle.net/rqevmp3y/1/
$("#angle-control").on('click', function (event) {
console.log('rotate');
var curAngle = canvas._objects[0].getAngle();
canvas._objects[0].setAngle(curAngle+90);
canvas.renderAll();
});
$("#rangeControl").on('change', function (event) {
console.log('rotate from range',$(this).val());
var curAngle = canvas._objects[0].getAngle();
canvas._objects[0].setAngle(curAngle+parseInt($(this).val()));
canvas.renderAll();
});

Remove/disable jquery plugin on button click

I am using jQuery ImageAreaSelect for image area selection like this:
$('#image').imgAreaSelect({}); //#image is a img id
Below this image, I have a bunch of image thumbnails, clicking on which will populate that image as #image. This way user can load each image and then select its area.
My problem is that when a new image is loaded, the dotted line which indicates the area selected for previous image still remains and gets shown on the newly loaded image. I do not want this and want this to go away every time a new image is loaded.
I read and tried this answer and this answer but they are not working for me...
My current (non-working) code is:
$('#load').click(function() {
$('#image').imgAreaSelect({hide:true,remove:true}); //try to remove old instance
$('#image').imgAreaSelect({}); //create new instance...
});
Any help is appreciated.
I have never used such pluggin but the documentation explains how to disable/re-enable it.
Save the variable when you initialize the pluggin
var ias = $('#image').imgAreaSelect( // your original initalization
Then call disable on it as the documentation states:
ias.setOptions({hide:true,remove:true})
Try this way
$('#load').click(function() {
$('#image').cancelSelection();
});

How to reset the Jcrop plugin? I.e. How to allow changing the source of the target image?

The application I'm working on allows users to add an unlimited number of images onto a viewport. With those images, a series of operations are allowed: resize, drag, rotate, and crop. For the cropping feature, I'm using the Jcrop plugin.
When clicking on the control icon for cropping, a lightbox appears, that shows the selected image (the <img> element is one and the same, only the src attribute value changes each time) and allows the user to crop it. The event handler associated triggered when the crop icon is clicked is:
$(document).on("click", "div.cropper", function(){
var ctrl = $(this),
ref = ctrl.attr("reference"),
obj = returnObj(objects,ref),
target = $("#crop-target")
crop_params = {};
target.attr("src",obj.src);
target.Jcrop({
onSelect: function(c){
crop_params = c;
}
});
});
Given the code above, the cropping works perfectly, but ONLY with the first image I try it on. When I click on the "cropper" icon for any other images after that, the first image is shown.
How can I work around this problem?
PS: I've searched through the already existing questions about Jcrop and couldn't find an answer to my particular problem.
You just need to create a new img tag and start jCrop with that.
$('#parent_tag #img_to_crop').remove();
$('#parent_tag').html('<img id="img_to_crop"></img>');
$('#parent_tag #img_to_crop').Jcrop({ options ... });

Categories