updating a sprite source - animation

so I have a constant with the following:
const ghostFall2 = {
flap : function (){
this.speed = -this.jump;
} ,
animation2: [
{sX:2141, sY:195}
],
animation: [
{sX:1941, sY:202},
{sX:1753, sY:202},
],
cW : 226,
cH : 180,
x : 624,
y : 245,
w: 185,
h : 194,
frame: 0,
speed : 0,
gravity : 0.25,
jump : 6,
draw: function() {
if(ghostFall.y == 245){
state.current = state.game
let ghostFall2 = this.animation[this.frame];
ctx.drawImage(sprite, ghostFall2.sX, ghostFall2.sY, this.w, this.h, this.x, this.y, this.w, this.h)
}},
update: function(){
if(state.current == state.game){
ghostFall.draw = function(){}
this.frame += frames% 5 == 0 ?1:0;
this.frame = this.frame % this.animation.length
this.speed += this.gravity;
this.y += this.speed;
if(this.y > 245) {this.y = 245};
if(this.y < -100) {this.y = -100}
}},
chute: function(){
let ghostFall2 = this.animation2[0];
ctx.drawImage(sprite, ghostFall2.sX, ghostFall2.sY, this.cW, this.cH, this.x, this.y, this.w, this.h)
console.log(ghostFall2)
},
}
How it works is an requestAnimationFrame loop runs it over and over for the draw() and update() functions - these two work fine, draw paints the sprite item and update just makes it perpetually fall.
Then I also have an EventListener (click) which triggers the flap() function - basically makes it jump (then update brings it back down) - this one also works fine.
The problem comes when im trying to launch the chute() function (also via click event listener) which is supposed to replace my sprite source with a different image, but it never does so - why?
Just expecting for the sprite source to update
Link to codepen if you need to see the code in action - https://codepen.io/aurelradu91/pen/xxzEjQV

Related

Swap image sprite in HTML5 Canvas game

Trying to add basically different looking zombie. Is there a way to just swap the sprite or would I have to keep adding the code for class, scrolling etc.
class Zombie1 {
constructor({
position,
velocity,
distance = {
limit: 50,
traveled: 0
}
}) {
this.position = {
x: position.x,
y: position.y
}
this.velocity = {
x: velocity.x,
y: velocity.y
}
this.width = 97.49
this.height = 150
this.image = createImage(spriteZombie1)
this.frames = 0
this.distance = distance
}
draw() {
// c.fillStyle = 'red'
// c.fillRect(this.position.x, this.position.y, this.width, this.height)
c.drawImage(
this.image,
130 * this.frames,
0,
130,
150,
this.position.x,
this.position.y,
this.width,
this.height
)
}
update() {
this.frames++
if (this.frames >= 58) this.frames = 0
this.draw()
this.position.x += this.velocity.x
this.position.y += this.velocity.y
this.enemies = [];
if (this.position.y + this.height + this.velocity.y <= canvas.height)
this.velocity.y += gravity
// walk the zombie back and forth
this.distance.traveled += Math.abs(this.velocity.x)
if (this.distance.traveled > this.distance.limit) {
this.distance.traveled = 0
this.velocity.x = -this.velocity.x
}
}
}
zombies1 = [
new Zombie1({
position: {
x: 4000,
y: -950
},
velocity: {
x: -1,
y: 0
},
distance: {
limit: 7,
traveled: 0
}
}),
I have no problem adding more classes, it gets tedious and clutters the code. It won't let me post anymore code but that seems to be the important ones, other than importing the sprites.

How to work with multiple datasets in p5.js?

I want to create multiple line graphs with their own datasets into one p5.js sketch.
I created one line graph and do not know how to make another line graph to work with a different dataset.
https://editor.p5js.org/ariel.koh/sketches/VsRk3KxYp
I tried to create another preload table for my second graph but it did not work so I am still confused.
This was what I tried but I think it is not right, I never tried working with multiple datasets before so I am confused :(
let burnsdataset;
let canonattacksdataset;
function preload() {
// burns dataset
burnsdataset = loadTable("burns.csv", "csv", "header");
// canonattacks dataset
canonaattacksdataset = loadTable("canonattacks.csv", "csv",
"header");
}
You're on the right track loading the data.
The p5.js code you posted is a bit convoluted, here only a few examples:
the year labels a manually drawn, for each chart (even though the data is contained in the csv files)
if the text is simply drawn for the years but separate style, coordinate transformations, etc. are used then the push()/pop() call don't add anything.(e.g push();let sbm = 'Saul Bass Movies';...)
the drawLineGraph() function is defined twice (which might get you into variable shadowing bugs) and might be accidentally called within itself
No wonder you're confused.
I'd simplify as much as possible:
get back to loading and displaying one graph
load the second dataset (as you already correctly do above)
display the second graph
For example:
// file -> duplicate and file -> save
// this sketch first before you
// start working on it.
//
//
//
// Graph from Data, Line graph example
//
// Slides:
// http://slides.com/sojamo/cid-3-2122/fullscreen#/12/5
let burnsdataset;
let canonattacksdataset;
function preload() {
// burns dataset
burnsdataset = loadTable("burns.csv", "csv", "header");
canonaattacksdataset = loadTable("canonattacks.csv", "csv", "header");
}
function setup() {
// if you add SVG as 3rd parameter and then
// press s, the canvas will be saved as SVG file
createCanvas(displayWidth, displayHeight, SVG);
}
function draw() {
background(184, 37, 0);
//bottom label title
push();
textSize(14);
textFont("inconsolata");
textStyle(BOLDITALIC);
fill(243, 230, 214);
text("Burns", 30, 20, 330, 150); // Text wraps within text box
pop();
//linegraph
drawLineGraph({
dataset: burnsdataset,
column: 1,
x: 30,
y: 50,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
//bottom label title
push();
textSize(14);
textFont("inconsolata");
textStyle(BOLDITALIC);
fill(243, 230, 214);
text("Canon Attacks", 30, 250, 330, 150); // Text wraps within text box
pop();
//linegraph
drawLineGraph({
dataset: canonaattacksdataset,
column: 1,
x: 30,
y: 280,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
}
function drawLineGraph(theProps = {}) {
let values = theProps.dataset.getColumn(theProps.column);
let minValue = min(values);
let maxValue = max(values);
let x = theProps.x || 0;
let y = theProps.y || 0;
let w = theProps.w || 400;
let h = theProps.h || 300;
let bg = theProps.bg || color(255, 40);
let fg = theProps.fg || color(255, 120);
let dc = theProps.dc || color(0, 120);
let bc = theProps.bc || color(0, 120);
let lc = theProps.lc || color(255);
let thickness = theProps.thickness || 1;
let isLabel = theProps.isLabel || false;
let isCurve = theProps.isCurve || false;
let isDots = theProps.isDots || false;
let isBackground = theProps.isBackground || false;
let spacing = w / (values.length - 1);
let marginTopBottom = 20;
// we will calcualte the x and y values for each
// point first, because we need it later a couple
// of times.
let xx = [];
let yy = [];
let n = values.length;
for (let i = 0; i < n; i++) {
xx[i] = i * spacing;
yy[i] = map(
values[i],
minValue,
maxValue,
-marginTopBottom,
marginTopBottom - h
);
}
push();
translate(x, y);
translate(0, h);
// 1. draw background
if (isBackground == true) {
fill(bg);
rect(0, 0, w, -h);
// 2. draw grid
noStroke();
for (let i = 0; i < n - 1; i++) {
// fill(255,i%2 == 0 ? 80:40);
rect(xx[i], 0, 1, -h);
}
}
// 3. draw curved line graph
noFill();
stroke(lc);
strokeWeight(thickness);
beginShape();
if (isCurve == true) {
vertex(xx[0], yy[0]);
}
for (let i = 0; i < n; i++) {
let fn = isCurve == true ? curveVertex : vertex;
fn(xx[i], yy[i]);
}
if (isCurve == true) {
vertex(xx[n - 1], yy[n - 1]);
}
endShape();
// 4. draw dot / label for each value
noStroke();
// finally lets draw the dots and
// labels if enabled
let d = thickness + 8;
for (let i = 0; i < n; i++) {
push();
translate(xx[i], yy[i]);
if(isDots == true) {
fill(bc);
ellipse(0, 0, d + 4, d + 4);
fill(dc);
ellipse(0, 0, d, d);
}
if (isLabel == true) {
fill(lc)
rotate(-0.5);
textSize(7);
text(values[i], d, -d);
}
pop();
}
pop();
}
With that working you can focus on making the code nicer.
Taking the idea of "don't repeat yourself(DRY)" you can notice a few patterns that could be improved:
you try to not just draw the graph, but also also display the graph's
label: perhaps the drawLineGraph() could include that
you seem to manually be drawing every single year label, even though the data is already in the dataset and the x position is already calculated to display the points of the graph
Tackling point 1 is fairly straight foward: simply move the label drawing instrunctions inside the function, handle the extra argument to get the label text and adjust coordinates so they're relative to the graph.
Here's a modified version of the above integrating label as part of the drawLineGraph() function:
// file -> duplicate and file -> save
// this sketch first before you
// start working on it.
//
//
//
// Graph from Data, Line graph example
//
// Slides:
// http://slides.com/sojamo/cid-3-2122/fullscreen#/12/5
let burnsdataset;
let canonattacksdataset;
function preload() {
// burns dataset
burnsdataset = loadTable("burns.csv", "csv", "header");
canonaattacksdataset = loadTable("canonattacks.csv", "csv", "header");
}
function setup() {
// if you add SVG as 3rd parameter and then
// press s, the canvas will be saved as SVG file
createCanvas(displayWidth, displayHeight, SVG);
}
function draw() {
background(184, 37, 0);
//linegraph
drawLineGraph({
dataset: burnsdataset,
label: "Burns",
column: 1,
x: 30,
y: 50,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
//linegraph
drawLineGraph({
dataset: canonaattacksdataset,
label: "Canon Attacks",
column: 1,
x: 30,
y: 280,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
}
function drawLineGraph(theProps = {}) {
let values = theProps.dataset.getColumn(theProps.column);
let minValue = min(values);
let maxValue = max(values);
let x = theProps.x || 0;
let y = theProps.y || 0;
let w = theProps.w || 400;
let h = theProps.h || 300;
let bg = theProps.bg || color(255, 40);
let fg = theProps.fg || color(255, 120);
let dc = theProps.dc || color(0, 120);
let bc = theProps.bc || color(0, 120);
let lc = theProps.lc || color(255);
let thickness = theProps.thickness || 1;
let isLabel = theProps.isLabel || false;
let isCurve = theProps.isCurve || false;
let isDots = theProps.isDots || false;
let isBackground = theProps.isBackground || false;
let label = theProps.label || "";
let spacing = w / (values.length - 1);
let marginTopBottom = 20;
//bottom label title
push();
textSize(14);
textFont("inconsolata");
textStyle(BOLDITALIC);
fill(243, 230, 214);
text(label, x, y + h + marginTopBottom * 0.5, w, h); // Text wraps within text box
pop();
// we will calculate the x and y values for each
// point first, because we need it later a couple
// of times.
let xx = [];
let yy = [];
let n = values.length;
for (let i = 0; i < n; i++) {
xx[i] = i * spacing;
yy[i] = map(
values[i],
minValue,
maxValue,
-marginTopBottom,
marginTopBottom - h
);
}
push();
translate(x, y);
translate(0, h);
// 1. draw background
if (isBackground == true) {
fill(bg);
rect(0, 0, w, -h);
// 2. draw grid
noStroke();
for (let i = 0; i < n - 1; i++) {
// fill(255,i%2 == 0 ? 80:40);
rect(xx[i], 0, 1, -h);
}
}
// 3. draw curved line graph
noFill();
stroke(lc);
strokeWeight(thickness);
beginShape();
if (isCurve == true) {
vertex(xx[0], yy[0]);
}
for (let i = 0; i < n; i++) {
let fn = isCurve == true ? curveVertex : vertex;
fn(xx[i], yy[i]);
}
if (isCurve == true) {
vertex(xx[n - 1], yy[n - 1]);
}
endShape();
// 4. draw dot / label for each value
noStroke();
// finally lets draw the dots and
// labels if enabled
let d = thickness + 8;
for (let i = 0; i < n; i++) {
push();
translate(xx[i], yy[i]);
if(isDots == true) {
fill(bc);
ellipse(0, 0, d + 4, d + 4);
fill(dc);
ellipse(0, 0, d, d);
}
if (isLabel == true) {
fill(lc)
rotate(-0.5);
textSize(7);
text(values[i], d, -d);
}
pop();
}
pop();
}
And here's a modified version of the above that renders the labels on the x axis (year):
// file -> duplicate and file -> save
// this sketch first before you
// start working on it.
//
//
//
// Graph from Data, Line graph example
//
// Slides:
// http://slides.com/sojamo/cid-3-2122/fullscreen#/12/5
let burnsdataset;
let canonattacksdataset;
function preload() {
// burns dataset
burnsdataset = loadTable("burns.csv", "csv", "header");
// canon attacks dataset
canonaattacksdataset = loadTable("canonattacks.csv", "csv", "header");
}
function setup() {
// if you add SVG as 3rd parameter and then
// press s, the canvas will be saved as SVG file
createCanvas(displayWidth, displayHeight, SVG);
drawPlots();
}
function drawPlots() {
background(184, 37, 0);
// burnsdataset linegraph
drawLineGraph({
dataset: burnsdataset,
label: "Burns",
xColumn: 0,
yColumn: 1,
x: 30,
y: 50,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
// canonaattacksdataset linegraph
drawLineGraph({
dataset: canonaattacksdataset,
label: "Canon Attacks",
xColumn: 0,
yColumn: 1,
x: 30,
y: 300,
w: width - 1500,
h: height - 900,
lc: color(255, 255, 255),
dc: color(169, 247, 111),
thickness: 1.5,
isCurve: true,
isDots: true,
isBackground: true,
isLabel: true,
});
}
function drawLineGraph(theProps = {}) {
let values = theProps.dataset.getColumn(theProps.yColumn);
let minValue = min(values);
let maxValue = max(values);
let labels = theProps.dataset.getColumn(theProps.xColumn);
let x = theProps.x || 0;
let y = theProps.y || 0;
let w = theProps.w || 400;
let h = theProps.h || 300;
let bg = theProps.bg || color(255, 40);
let fg = theProps.fg || color(255, 120);
let dc = theProps.dc || color(0, 120);
let bc = theProps.bc || color(0, 120);
let lc = theProps.lc || color(255);
let thickness = theProps.thickness || 1;
let isLabel = theProps.isLabel || false;
let isCurve = theProps.isCurve || false;
let isDots = theProps.isDots || false;
let isBackground = theProps.isBackground || false;
let label = theProps.label || "";
let spacing = w / (values.length - 1);
let marginTopBottom = 20;
// y position for labels (e.g. years)
let labelsY = marginTopBottom * 0.5;
//bottom label title
push();
textSize(14);
textFont("inconsolata");
textStyle(BOLDITALIC);
fill(243, 230, 214);
text(label, x, y - marginTopBottom, w, h); // Text wraps within text box
pop();
// we will calculate the x and y values for each
// point first, because we need it later a couple
// of times.
let xx = [];
let yy = [];
let n = values.length;
for (let i = 0; i < n; i++) {
xx[i] = i * spacing;
yy[i] = map(
values[i],
minValue,
maxValue,
-marginTopBottom,
marginTopBottom - h
);
}
push();
translate(x, y);
translate(0, h);
// 1. draw background
if (isBackground == true) {
fill(bg);
rect(0, 0, w, -h);
// 2. draw grid
noStroke();
for (let i = 0; i < n - 1; i++) {
// fill(255,i%2 == 0 ? 80:40);
rect(xx[i], 0, 1, -h);
}
}
// 3. draw curved line graph
noFill();
stroke(lc);
strokeWeight(thickness);
beginShape();
if (isCurve == true) {
vertex(xx[0], yy[0]);
}
for (let i = 0; i < n; i++) {
let fn = isCurve == true ? curveVertex : vertex;
fn(xx[i], yy[i]);
// label per data point
push();
noStroke();
fill(255);
textSize(9);
textAlign(CENTER);
text(labels[i], xx[i], labelsY);
pop();
}
if (isCurve == true) {
vertex(xx[n - 1], yy[n - 1]);
}
endShape();
// 4. draw dot / label for each value
noStroke();
// finally lets draw the dots and
// labels if enabled
let d = thickness + 8;
for (let i = 0; i < n; i++) {
push();
translate(xx[i], yy[i]);
if(isDots == true) {
fill(bc);
ellipse(0, 0, d + 4, d + 4);
fill(dc);
ellipse(0, 0, d, d);
}
if (isLabel == true) {
fill(lc)
rotate(-0.5);
textSize(7);
text(values[i], d, -d);
}
pop();
}
pop();
}
// if you want to use the SVG export
// option, go to setup and enable SVG mode
function keyPressed() {
if (key === "s") {
saveSVG("line-graph.svg");
}
}
There's one slight detail snuck in there: I've renamed draw() to drawPlots() and called it once from setup(). That is to render the plots a single time since they don't change and save CPU resources. If you do plan to have some sort interation changing these graphs then you should use draw().

Animated rectangle used as an audio playhead isn't displaying properly

I'm building a drum machine following a tutorial on Youtube, and I'm trying to use a rectangle as a playhead, which is animating in time with the beat.
The "Space" key activates the drum loop. The variable 'sPat' (sequence pattern), defined as an array [1, 2, 3... etc.] shows where the rectangle should be drawn. beatIndex represents the position taken from that array.
It seems to be working except the rectangle doesn't display most of the time, it's blinking and it is only visible about 5% of the time, randomly. I tried playing around with the rectangle parameters to see what is happenning, setting it to a fixed position and tried Firefox and Chrome. I'm not at all familiar with p5 yet.
What I need help with is:
why isn't the rectangle displaying?
why are the dots becomming colored in red as soon as I hit Space and how to prevent this?
I tried to minimize the code to a smaller working version. The 'sequence' function drawing the rectangle is at the end. You can also run it here: https://editor.p5js.org/dmihaescu/sketches/OFZm52gmF
let dum, dPat, dPhrase, drums;
let beatLength;
let sPat;
var canvas;
var cellWidth;
let beatIndex;
function setup() {
canvas = createCanvas(600, 100);
beatLength = 16;
cellWidth = width/beatLength;
beatIndex = 0;
dum = loadSound('assets/dum.flac', () => {});
dPat = [1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0];
sPat = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
drums = new p5.Part();
drums.setBPM('45')
drums.addPhrase('dum', (time) => {dum.play(time)}, dPat);
drums.addPhrase('seq', sequence, sPat);
}
function keyPressed() {
if(key === " ") {
if(dum.isLoaded()) {
if(!drums.isPlaying) {
drums.loop();
} else {
drums.stop();
}
} else {
console.log("not yet loaded");
}
}
}
function draw() {
background(0);
stroke("gray");
strokeWeight(2);
for (let i = 0; i < beatLength+1; i++) {
line(i*width/beatLength, 0, i*width/beatLength, height);
}
for (let i = 0; i < 4; i++) {
line(0, i*height/3, width, i*height/3);
}
noStroke();
for (let i = 0; i < beatLength; i++) {
if(dPat[i] === 1) {
ellipse(i*width/beatLength+0.5*width/beatLength,height/2,10);
}
}
}
function sequence (time, beatIndex) {
stroke('red');
fill(255,0,0,50);
rect((beatIndex-1)*cellWidth, 0, 50, height);
}
No need for a seperate function just put the below code in draw function :-
stroke('red');
fill(255,0,0,50);
rect((beatIndex-1)*cellWidth, 0, 50, height);
Try and tell whether it worked out or not

How can resume animation Kineticjs canvas?

I have problem with resume animation after stop it. Any suggestion ? I using kineticjs to make element run along the path, after i reach the end, the animation stop for 2 second then start again.
here my code :
var stage = new Kinetic.Stage({
container: 'canvas',
height: 484,
width: 478
});
var layer = new Kinetic.Layer();
stage.add(layer);
var img = new Image();
img.src = 'images/ani/bullet_blue.png';
var circle = new Image();
circle.src = 'images/ani/1.png';
var shapeCircle = new Kinetic.Image({
x: 10,
y: 10,
image: circle,
width: circle.width,
height: circle.height,
offset: {
x: 0,
y: 0
}
});
layer.add(shapeCircle);
layer.draw();
function animation(points, shape, duration, loop, callback) {
layer.add(shape);
window.anim = new Kinetic.Animation(function (frame) {
var time = frame.time, timeDiff = frame.timeDiff, frameRate = frame.frameRate;
var percent = time / duration, scale = 0.5, opacity = 0;
if (percent < 0.05 || percent > 0.95) opacity = 0;
else opacity = 1;
// scale calculate
if (percent < 0.5) {
scale += percent
}
else if (percent > 0.5) {
scale = 1 - (percent - 0.5)
}
if (percent > 1) {
anim.stop();
percent = 0;
setTimeout(function () { anim.start(); }, 500);
} else {
var pos = Math.ceil(percent * points.length);
pos = pos > (points.length - 1) ? (points.length - 1) : pos;
if (pos == points.length - 1) anim.stop();
shape.setScale(scale, scale);
shape.setOpacity(opacity);
shape.setPosition(points[pos].x, points[pos].y);
}
}, layer);
anim.start();
}
animation(points1, new Kinetic.Image({
x: points1[0].x,
y: points1[0].y,
image: img,
width: img.width,
height: img.height,
opacity: 0,
scaleX: 0.5,
scaleY: 0.5,
offset: {
x: 15,
y: 30
}
}), 2000);
If you want a repeating animation, you might consider a tween instead.
When a tween finishes, it fires a finished event. In that finished handler, you can:
Reset the tween to the starting position using tween.reset,
Start a timer to wait 2 seconds using setTimer,
When the timer fires, restart the tween using tween.start.

Kineticjs - can not control scaled image

when you drag images you can control their moving with dragBoundFunc. Is there something similar when you scaling? I want to set an image area in "part of a stage" and when i setScale for this image and make it bigger, i don't want to see parts which is bigger than image area i've set before. is it possible? Here is my fiddle..
var stage = new Kinetic.Stage({
container : 'canvas',
width : 620,
height : 236
});
var layer = new Kinetic.Layer();
var leftImage = new Image();
leftImage.src = "http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg";
var leftImg = new Kinetic.Image({
x : stage.getWidth() - 480,
y : stage.getHeight() - 126,
image : leftImage,
width : 190,
height : 124,
offset : [95, 62],
draggable : true,
dragBoundFunc: function(pos) {
var x=stage.getWidth() - 480;
var y=stage.getHeight() - 126;
var radius = 50;
var scale = radius/ Math.sqrt(Math.pow(pos.x - x, 2) + Math.pow(pos.y - y, 2));
if(scale < 1)
return {
y: Math.round((pos.y - y) * scale + y),
x: Math.round((pos.x - x) * scale + x)
};
else
return pos;
}
});
var rectLeft = new Kinetic.Rect({
x : 38,
y : 20,
width : 232,
height : 184,
stroke:'red',
listening:false
});
var rectRight = new Kinetic.Rect({
x : 350,
y : 20,
width : 232,
height : 184,
stroke:'green',
listening:false
});
layer.add(leftImg);
layer.add(rectLeft);
layer.add(rectRight);
stage.add(layer);
document.getElementById('larger').addEventListener('click', function() {
leftImg.setScale(leftImg.getScale().x + 1.5);
layer.draw();
}, false);
Sure.
You can clip your scaled image into a fixed area of the stage by wrapping your image in a group and setting the clip property of that group to your fixed area.
If you set the clip property on a group like this:
var group=new Kinetic.Group({
x:100,
y:100,
width: originalImageWidth,
height: originalImageHeight,
clip: [0,0,originalImageWidth,originalImageHeight]
});
Then the image you put in the group will be clipped to stage #100,100 and size == original image size.
If you later scale the image larger, the clipping area will act as a "viewport" into part of the larger image.

Resources